commit 48d35d7

xplshn  ·  2026-07-02 05:19:17 +0000 UTC
parent a3cf753
Build system changes - Update README

Signed-off-by: xplshn <anto@xplshn.com.ar>
19 files changed,  +1436, -562
M README
+87, -28
  1@@ -1,7 +1,7 @@
  2 .POSIX:
  3-include config.mk
  4-.SUFFIXES: .y .o .c
  5+include scripts/mk/config.mk
  6 
  7+.SUFFIXES: .y .o .c
  8 HDR =\
  9 	shared/arg.h\
 10 	shared/compat.h\
 11@@ -129,7 +129,6 @@ POSIX_BIN_ALL =\
 12 	cmd/posix/df\
 13 	cmd/posix/diff\
 14 	cmd/posix/patch\
 15-	cmd/posix/diff3\
 16 	cmd/posix/dirname\
 17 	cmd/posix/du\
 18 	cmd/posix/echo\
 19@@ -193,7 +192,8 @@ POSIX_BIN_ALL =\
 20 	cmd/posix/awk/awk\
 21 	cmd/posix/sh/sh\
 22 	cmd/posix/pax\
 23-	cmd/posix/make/make
 24+	cmd/posix/make/make\
 25+	cmd/posix/bc
 26 
 27 LINUX_BIN_ALL =\
 28 	cmd/linux/blkdiscard\
 29@@ -205,6 +205,7 @@ LINUX_BIN_ALL =\
 30 	cmd/linux/hwclock\
 31 	cmd/linux/insmod\
 32 	cmd/linux/lsmod\
 33+	cmd/linux/lsusb\
 34 	cmd/linux/modprobe\
 35 	cmd/linux/depmod\
 36 	cmd/linux/mkswap\
 37@@ -217,6 +218,7 @@ LINUX_BIN_ALL =\
 38 	cmd/linux/swapoff\
 39 	cmd/linux/swapon\
 40 	cmd/linux/switch_root\
 41+	cmd/linux/sysctl\
 42 	cmd/linux/tunctl\
 43 	cmd/linux/umount\
 44 	cmd/linux/unshare\
 45@@ -277,6 +279,7 @@ PSEUDO_BIN_ALL =\
 46 	cmd/pseudo/xinstall\
 47 	cmd/pseudo/yes\
 48 	cmd/pseudo/base64\
 49+	cmd/pseudo/mkpasswd\
 50 	cmd/extra/b3sum\
 51 	cmd/extra/blkid\
 52 	cmd/extra/lsblk\
 53@@ -292,7 +295,8 @@ PSEUDO_BIN_ALL =\
 54 	cmd/pseudo/free\
 55 	cmd/pseudo/pidof\
 56 	cmd/pseudo/pwdx\
 57-	cmd/pseudo/uptime
 58+	cmd/pseudo/uptime\
 59+	cmd/pseudo/diff3
 60 
 61 MAKEOBJ =\
 62 	cmd/posix/make/defaults.o\
 63@@ -393,6 +397,7 @@ BIN_fsfreeze_1 = cmd/linux/fsfreeze
 64 BIN_hwclock_1 = cmd/linux/hwclock
 65 BIN_insmod_1 = cmd/linux/insmod
 66 BIN_lsmod_1 = cmd/linux/lsmod
 67+BIN_lsusb_1 = cmd/linux/lsusb
 68 BIN_modprobe_1 = cmd/linux/modprobe
 69 BIN_depmod_1 = cmd/linux/depmod
 70 BIN_mkswap_1 = cmd/linux/mkswap
 71@@ -405,6 +410,7 @@ BIN_swaplabel_1 = cmd/linux/swaplabel
 72 BIN_swapoff_1 = cmd/linux/swapoff
 73 BIN_swapon_1 = cmd/linux/swapon
 74 BIN_switch_root_1 = cmd/linux/switch_root
 75+BIN_sysctl_1 = cmd/linux/sysctl
 76 BIN_tunctl_1 = cmd/linux/tunctl
 77 BIN_umount_1 = cmd/linux/umount
 78 BIN_unshare_1 = cmd/linux/unshare
 79@@ -462,13 +468,15 @@ BIN_whoami_1 = cmd/pseudo/whoami
 80 BIN_xinstall_1 = cmd/pseudo/xinstall
 81 BIN_yes_1 = cmd/pseudo/yes
 82 BIN_base64_1 = cmd/pseudo/base64
 83+BIN_mkpasswd_1 = cmd/pseudo/mkpasswd
 84+BIN_bc_1 = cmd/posix/bc
 85 BIN_b3sum_1 = cmd/extra/b3sum
 86 BIN_blkid_1 = cmd/extra/blkid
 87 BIN_lsblk_1 = cmd/extra/lsblk
 88 BIN_fdisk_1 = cmd/extra/fdisk
 89 BIN_sync_1 = cmd/extra/sync
 90 BIN_yap_1 = cmd/extra/yap/yap
 91-BIN_diff3_1 = cmd/posix/diff3
 92+BIN_diff3_1 = cmd/pseudo/diff3
 93 BIN_ar_1 = cmd/dev/ar/ar
 94 BIN_as_1 = cmd/dev/as/as
 95 BIN_ld_1 = cmd/dev/ld/ld
 96@@ -560,7 +568,8 @@ POSIX_BIN = \
 97 	$(BIN_awk_$(BUILD_POSIX_AWK)) \
 98 	$(BIN_sh_$(BUILD_POSIX_SH)) \
 99 	$(BIN_pax_$(BUILD_POSIX_PAX)) \
100-	$(BIN_make_$(BUILD_POSIX_MAKE))
101+	$(BIN_make_$(BUILD_POSIX_MAKE)) \
102+	$(BIN_bc_$(BUILD_POSIX_BC))
103 
104 LINUX_BIN = \
105 	$(BIN_blkdiscard_$(BUILD_LINUX_BLKDISCARD)) \
106@@ -572,6 +581,7 @@ LINUX_BIN = \
107 	$(BIN_hwclock_$(BUILD_LINUX_HWCLOCK)) \
108 	$(BIN_insmod_$(BUILD_LINUX_INSMOD)) \
109 	$(BIN_lsmod_$(BUILD_LINUX_LSMOD)) \
110+	$(BIN_lsusb_$(BUILD_LINUX_LSUSB)) \
111 	$(BIN_modprobe_$(BUILD_LINUX_MODPROBE)) \
112 	$(BIN_depmod_$(BUILD_LINUX_DEPMOD)) \
113 	$(BIN_mkswap_$(BUILD_LINUX_MKSWAP)) \
114@@ -584,6 +594,7 @@ LINUX_BIN = \
115 	$(BIN_swapoff_$(BUILD_LINUX_SWAPOFF)) \
116 	$(BIN_swapon_$(BUILD_LINUX_SWAPON)) \
117 	$(BIN_switch_root_$(BUILD_LINUX_SWITCH_ROOT)) \
118+	$(BIN_sysctl_$(BUILD_LINUX_SYSCTL)) \
119 	$(BIN_tunctl_$(BUILD_LINUX_TUNCTL)) \
120 	$(BIN_umount_$(BUILD_LINUX_UMOUNT)) \
121 	$(BIN_unshare_$(BUILD_LINUX_UNSHARE)) \
122@@ -644,11 +655,13 @@ PSEUDO_BIN = \
123 	$(BIN_xinstall_$(BUILD_PSEUDO_XINSTALL)) \
124 	$(BIN_yes_$(BUILD_PSEUDO_YES)) \
125 	$(BIN_base64_$(BUILD_PSEUDO_BASE64)) \
126-	$(BIN_b3sum_$(BUILD_PSEUDO_B3SUM)) \
127-	$(BIN_blkid_$(BUILD_PSEUDO_BLKID)) \
128-	$(BIN_lsblk_$(BUILD_PSEUDO_LSBLK)) \
129-	$(BIN_fdisk_$(BUILD_PSEUDO_FDISK)) \
130-	$(BIN_sync_$(BUILD_PSEUDO_SYNC)) \
131+	$(BIN_mkpasswd_$(BUILD_PSEUDO_MKPASSWD)) \
132+	$(BIN_b3sum_$(BUILD_EXTRA_B3SUM)) \
133+	$(BIN_blkid_$(BUILD_EXTRA_BLKID)) \
134+	$(BIN_lsblk_$(BUILD_EXTRA_LSBLK)) \
135+	$(BIN_fdisk_$(BUILD_EXTRA_FDISK)) \
136+	$(BIN_sync_$(BUILD_EXTRA_SYNC)) \
137+	$(BIN_yap_$(BUILD_EXTRA_YAP)) \
138 	$(BIN_diff3_$(BUILD_PSEUDO_DIFF3)) \
139 	$(BIN_ar_$(BUILD_DEV_AR)) \
140 	$(BIN_as_$(BUILD_DEV_CC)) \
141@@ -713,30 +726,71 @@ cmd/posix/getconf.h:
142 
143 box: $(LIB)
144 	CC='$(CC)' CPPFLAGS='$(CPPFLAGS)' CFLAGS='$(CFLAGS)' \
145-	LDFLAGS='$(LDFLAGS)' LDLIBS='$(LDLIBS)' OBJCOPY='$(OBJCOPY)' \
146+	LDFLAGS='$(LDFLAGS)' LDLIBS='$(LDLIBS) $(LDLIBS_TLS)' OBJCOPY='$(OBJCOPY)' \
147 	scripts/mkbox
148 
149-.PHONY: man clean
150+.PHONY: man clean install regen help
151 
152 scripts/mkman/mkman: scripts/mkman/main.go scripts/mkman/page.go scripts/mkman/parse.go scripts/mkman/mdoc.go
153 	cd scripts/mkman && go build -o mkman .
154 
155 man: scripts/mkman/mkman
156-	@for src in $(POSIX_BIN_ALL:=.c) $(PSEUDO_BIN_ALL:=.c); do \
157+	find cmd -type f -name '*.c' | while read -r src; do \
158 		if [ -f "$$src" ] && grep -qE '!man|\?man' "$$src"; then \
159-			base=$$(basename $$src .c); \
160-			mkdir -p man/man1; \
161-			scripts/mkman/mkman -fmt mdoc -config config.mk -section 1 "$$src" > "man/man1/$$base.1"; \
162-			scripts/mkman/mkman -fmt txt -config config.mk -section 1 "$$src" > "man/man1/$$base.1.txt"; \
163+			sub=$${src#cmd/}; \
164+			cat=$${sub%%/*}; \
165+			base=$${src##*/}; \
166+			base=$${base%.c}; \
167+			name=$${sub#*/}; \
168+			if [ "$${name}" != "$${base}.c" ]; then \
169+				name=$${name%%/*}; \
170+			else \
171+				name=$$base; \
172+			fi; \
173+			u_group=$$(echo "$$cat" | tr 'a-z' 'A-Z'); \
174+			u_tool=$$(echo "$$name" | tr 'a-z-' 'A-Z_'); \
175+			var_name="BUILD_$${u_group}_$${u_tool}"; \
176+			val=""; \
177+			if [ -f scripts/mk/config.kv ]; then \
178+				val=$$(grep "^$${var_name}=" scripts/mk/config.kv | cut -d= -f2 | tr -d '"'); \
179+			fi; \
180+			if [ "$$val" != "1" ]; then \
181+				continue; \
182+			fi; \
183+			case "$$cat" in \
184+				linux|net|xsi) sec=8 ;; \
185+				*)             sec=1 ;; \
186+			esac; \
187+			mkdir -p "man/man$${sec}"; \
188+			scripts/mkman/mkman -fmt mdoc -config scripts/mk/config.kv -section "$${sec}" "$$src" > "man/man$${sec}/$$name.$${sec}"; \
189+			scripts/mkman/mkman -fmt txt -config scripts/mk/config.kv -section "$${sec}" "$$src" > "man/man$${sec}/$$name.$${sec}.txt"; \
190 		fi; \
191 	done
192-	@for src in $(LINUX_BIN_ALL:=.c) $(NET_BIN_ALL:=.c) $(XSI_BIN_ALL:=.c); do \
193-		if [ -f "$$src" ] && grep -qE '!man|\?man' "$$src"; then \
194-			base=$$(basename $$src .c); \
195-			mkdir -p man/man8; \
196-			scripts/mkman/mkman -fmt mdoc -config config.mk -section 8 "$$src" > "man/man8/$$base.8"; \
197-			scripts/mkman/mkman -fmt txt -config config.mk -section 8 "$$src" > "man/man8/$$base.8.txt"; \
198-		fi; \
199+
200+regen:
201+	sh scripts/genconfig.sh
202+	$(MAKE) -f Makefile cmd/posix/getconf.h cmd/posix/bc.c cmd/posix/awk/awkgram.tab.c cmd/posix/awk/proctab.c cmd/posix/sh/token.h cmd/posix/sh/syntax.c cmd/posix/sh/nodes.c cmd/posix/sh/builtins.c
203+
204+help:
205+	@echo "Available targets:"
206+	@echo "  all       - Build all enabled utilities"
207+	@echo "  clean     - Clean build artifacts"
208+	@echo "  install   - Install binaries and man pages"
209+	@echo "  box       - Build the multicall binary (aruu-box)"
210+	@echo "  man       - Generate manual pages"
211+	@echo "  regen     - Regenerate build system files and config"
212+	@echo "  help      - Show this help message"
213+
214+install: all man
215+	@mkdir -p $(PREFIX)/bin $(MANPREFIX)/man1 $(MANPREFIX)/man8
216+	@find cmd -type f ! -name '*.*' -perm -100 | while read -r bin; do \
217+		printf "  INSTALL %s/bin/%s\n" "$(PREFIX)" "$${bin##*/}"; \
218+		cp "$$bin" "$(PREFIX)/bin/$${bin##*/}"; \
219+		chmod 755 "$(PREFIX)/bin/$${bin##*/}"; \
220+	done
221+	@find man/man1 man/man8 -type f -name '*.[18]' 2>/dev/null | while read -r f; do \
222+		sec=$${f%/*}; sec=$${sec##*/}; \
223+		cp "$$f" "$(MANPREFIX)/$${sec}/$${f##*/}"; \
224 	done
225 
226 clean:
227@@ -747,7 +801,7 @@ clean:
228 	@printf "  CLEAN compiled binaries\n"
229 	@rm -f $(POSIX_BIN_ALL) $(LINUX_BIN_ALL) $(NET_BIN_ALL) $(XSI_BIN_ALL) $(PSEUDO_BIN_ALL)
230 	@printf "  CLEAN generated headers\n"
231-	@rm -f cmd/posix/getconf.h cmd/posix/bc.c
232+	@rm -f cmd/posix/getconf.h cmd/posix/bc.c cmd/posix/bc.h
233 	@rm -f cmd/posix/awk/awkgram.tab.c cmd/posix/awk/awkgram.tab.h
234 	@rm -f cmd/posix/sh/token.h cmd/posix/sh/syntax.c cmd/posix/sh/syntax.h
235 	@rm -f cmd/posix/sh/nodes.c cmd/posix/sh/nodes.h cmd/posix/sh/builtins.c cmd/posix/sh/builtins.h
236@@ -863,7 +917,7 @@ cmd/posix/sh/syntax.c cmd/posix/sh/syntax.h: cmd/posix/sh/mksyntax
237 cmd/posix/sh/nodes.c cmd/posix/sh/nodes.h: cmd/posix/sh/mknodes cmd/posix/sh/nodetypes cmd/posix/sh/nodes.c.pat
238 	cd cmd/posix/sh && ./mknodes nodetypes nodes.c.pat
239 
240-cmd/posix/sh/builtins.c cmd/posix/sh/builtins.h: cmd/posix/sh/mkbuiltins cmd/posix/sh/builtins.def cmd/posix/sh/shell.h
241+cmd/posix/sh/builtins.c cmd/posix/sh/builtins.h: cmd/posix/sh/mkbuiltins cmd/posix/sh/builtins.def cmd/posix/sh/shell.h scripts/mk/config.kv
242 	cd cmd/posix/sh && sh mkbuiltins .
243 
244 cmd/posix/sh/token.h: cmd/posix/sh/mktokens
245@@ -1004,3 +1058,8 @@ cmd/dev/config.h cmd/dev/cc/config.h cmd/dev/version.h: cmd/dev/configure
246 	sh cmd/dev/configure
247 
248 $(AS_OBJ) $(LD_OBJ) $(CC1_OBJ) $(CPP_OBJ) cmd/dev/ar/ar.o cmd/dev/cc/cpp.o: cmd/dev/config.h
249+
250+scripts/mk/config.mk scripts/mk/config.kv: build.cfg scripts/genconfig.sh
251+	sh scripts/genconfig.sh
252+
253+Makefile: ;
+147, -65
  1@@ -29,6 +29,12 @@ done
  2 # shellcheck disable=SC1091
  3 . ./build.cfg
  4 
  5+# load config.kv if it exists to override and provide detected TLS settings
  6+if [ -f scripts/mk/config.kv ]; then
  7+        # shellcheck disable=SC1091
  8+        . scripts/mk/config.kv
  9+fi
 10+
 11 # cppflags derived from build.cfg; any feature_* added there is picked up automatically
 12 _feature_flags=""
 13 while IFS= read -r _line; do
 14@@ -44,35 +50,10 @@ done <<EOF
 15 $(tr ';' '\n' < build.cfg)
 16 EOF
 17 unset _line _key _val _trimmed
 18-CPPFLAGS="-Ishared -DPREFIX=\"$PREFIX\" -D_DEFAULT_SOURCE -D_GNU_SOURCE -D_NETBSD_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_FILE_OFFSET_BITS=64$_feature_flags"
 19-if [ "$FEATURE_USE_BEARSSL" = "1" ]; then
 20-        if pkg-config --exists libbearssl 2>/dev/null; then
 21-                CPPFLAGS="$CPPFLAGS $(pkg-config --cflags libbearssl)"
 22-                TLS_LDLIBS="$TLS_LDLIBS $(pkg-config --libs libbearssl)"
 23-        elif pkg-config --exists bearssl 2>/dev/null; then
 24-                CPPFLAGS="$CPPFLAGS $(pkg-config --cflags bearssl)"
 25-                TLS_LDLIBS="$TLS_LDLIBS $(pkg-config --libs bearssl)"
 26-        else
 27-                TLS_LDLIBS="$TLS_LDLIBS -LexternalRepos/BearSSL/build -lbearssl"
 28-        fi
 29-fi
 30-if [ "$FEATURE_USE_LIBRESSL" = "1" ]; then
 31-        if pkg-config --exists libtls 2>/dev/null; then
 32-                CPPFLAGS="$CPPFLAGS $(pkg-config --cflags libtls)"
 33-                TLS_LDLIBS="$TLS_LDLIBS $(pkg-config --libs libtls)"
 34-        else
 35-                TLS_LDLIBS="$TLS_LDLIBS -ltls"
 36-        fi
 37-fi
 38-if [ "$FEATURE_USE_OPENSSL" = "1" ]; then
 39-        if pkg-config --exists openssl 2>/dev/null; then
 40-                CPPFLAGS="$CPPFLAGS $(pkg-config --cflags openssl)"
 41-                TLS_LDLIBS="$TLS_LDLIBS $(pkg-config --libs openssl)"
 42-        else
 43-                TLS_LDLIBS="$TLS_LDLIBS -lssl -lcrypto"
 44-        fi
 45-fi
 46-unset _feature_flags
 47+
 48+CPPFLAGS="-Ishared -DPREFIX=\\\"\$PREFIX\\\" -D_DEFAULT_SOURCE -D_GNU_SOURCE -D_NETBSD_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_FILE_OFFSET_BITS=64$_feature_flags $CPPFLAGS_TLS"
 49+LDFLAGS="${LDFLAGS:-} $LDFLAGS_TLS"
 50+TLS_LDLIBS="$LDLIBS_TLS"
 51 
 52 CC=${CC:-cc}
 53 AR=${AR:-ar}
 54@@ -81,7 +62,7 @@ RANLIB=${RANLIB:-ranlib}
 55 PREFIX=${PREFIX:-/usr/local}
 56 MANPREFIX=${MANPREFIX:-$PREFIX/share/man}
 57 
 58-# shared headers; every object depends on these
 59+# shared headers, most objects depend on these
 60 HDR=$(echo shared/*.h)
 61 LIB="shared/libredline/libredline.a shared/libutil/libutil.a shared/libutf/libutf.a"
 62 
 63@@ -93,14 +74,12 @@ EXTRA_HDR=
 64 mtime() {
 65         stat -c '%Y' "$1" 2>/dev/null || stat -f '%m' "$1" 2>/dev/null || echo 0
 66 }
 67-
 68 newer_than() {
 69         local s t
 70         [ -e "$2" ] || return 0
 71         s=$(mtime "$1"); t=$(mtime "$2")
 72         [ "$s" -gt "$t" ]
 73 }
 74-
 75 any_newer_than() {
 76         local target="$1"; shift
 77         for src do
 78@@ -110,20 +89,17 @@ any_newer_than() {
 79 }
 80 
 81 # parallel job queue
 82+# objs_for must not run in a subshell, enqueue writes _qn/_queue in the current shell
 83 #
 84-# objs_for must not run in a subshell; enqueue writes _qn/_queue in the current shell
 85-
 86 _qn=0
 87 _queue=""
 88 _objs=""
 89-
 90 # wraps arg in single quotes, escaping embedded ones, for safe eval
 91 shquote() {
 92         printf "'"
 93         printf '%s' "$1" | sed "s/'/'\\\\''/g"
 94         printf "'"
 95 }
 96-
 97 enqueue() {
 98         local desc="$1" cmd="$2"
 99         _qn=$((_qn + 1))
100@@ -135,7 +111,6 @@ enqueue() {
101         } > "$s"
102         _queue="$_queue $_qn"
103 }
104-
105 # silently skipped on systems without /proc/loadavg
106 _wait_for_load() {
107         [ "$LOAD" -eq 0 ] && return 0
108@@ -146,7 +121,6 @@ _wait_for_load() {
109                 sleep 1
110         done
111 }
112-
113 drain() {
114         [ -z "$_queue" ] && return 0
115         local n
116@@ -164,7 +138,7 @@ drain() {
117         _queue=""
118 }
119 
120-# compile and link primitives
121+# compile and link routines
122 #
123 compile_c() {
124         local src="$1" obj="$2"; shift 2
125@@ -172,13 +146,12 @@ compile_c() {
126         any_newer_than "$obj" "$src" $HDR $EXTRA_HDR || return 0
127         enqueue "  CC  $obj" "$CC $* $CPPFLAGS $CFLAGS -o $obj -c $src"
128 }
129-
130 link_bin() {
131         local bin="$1" objs="" libs="" sep=0; shift
132         for a do
133                 if   [ "$a" = "--" ]; then sep=1
134                 elif [ "$sep" = 0  ]; then objs="$objs $a"
135-                else                        libs="$libs $a"
136+                else                       libs="$libs $a"
137                 fi
138         done
139         drain
140@@ -192,7 +165,6 @@ link_bin() {
141                 eval "$CC $LDFLAGS -o $bin $objs $libs $LDLIBS"
142         fi
143 }
144-
145 # writes to _objs rather than stdout so the caller avoids a subshell that
146 # would discard enqueued jobs
147 objs_for() {
148@@ -208,8 +180,8 @@ objs_for() {
149 }
150 
151 # static libraries
152-#
153 # both directories enqueued before the single drain so they compile in parallel
154+#
155 build_lib() {
156         local utf_objs util_objs redline_objs
157         objs_for shared/libutf "" ""
158@@ -244,7 +216,6 @@ build_lib() {
159 #
160 cfgvar() {
161         local cat="$1" base="$2"
162-        [ "$cat" = extra ] && cat=pseudo
163         printf 'BUILD_%s_%s' "$cat" "$base" | tr 'a-z-' 'A-Z_'
164 }
165 
166@@ -355,7 +326,7 @@ build_sh() {
167                 (cd "$dir" && ./mknodes nodetypes nodes.c.pat)
168         }
169 
170-        any_newer_than "$dir/builtins.c" "$dir/mkbuiltins" "$dir/builtins.def" "$dir/shell.h" && {
171+        any_newer_than "$dir/builtins.c" "$dir/mkbuiltins" "$dir/builtins.def" "$dir/shell.h" scripts/mk/config.kv && {
172                 printf '  GEN   %s/builtins.c\n' "$dir"
173                 (cd "$dir" && sh mkbuiltins .)
174         }
175@@ -375,6 +346,26 @@ build_make() {
176         link_bin "$dir/make" $_objs -- $LIB
177 }
178 
179+build_bc() {
180+        cfg_enabled BUILD_POSIX_BC || return 0
181+        local src=cmd/posix/bc.c
182+
183+        any_newer_than "$src" cmd/posix/bc.y && {
184+                printf '  GEN   %s\n' "$src"
185+                if command -v yacc >/dev/null 2>&1; then
186+                        yacc -o "$src" cmd/posix/bc.y
187+                elif command -v bison >/dev/null 2>&1; then
188+                        bison -o "$src" cmd/posix/bc.y
189+                else
190+                        printf 'bc: no yacc/bison found\n' >&2; return 1
191+                fi
192+        }
193+
194+        compile_c "$src" "${src%.c}.o"
195+        drain
196+        link_bin cmd/posix/bc "${src%.c}.o" -- $LIB
197+}
198+
199 build_posix() {
200         cfg_enabled BUILD_POSIX_GETCONF && [ ! -f cmd/posix/getconf.h ] && {
201                 printf '  GEN   cmd/posix/getconf.h\n'
202@@ -382,6 +373,7 @@ build_posix() {
203         }
204         build_simple_tools posix
205         build_awk
206+        build_bc
207         build_sh
208         build_make
209 }
210@@ -460,42 +452,46 @@ man_section() {
211 }
212 
213 build_man_for() {
214-        local var="$1" src="$2" base sec out_mdoc out_txt
215+        local var="$1" src="$2" name="$3" sec out_mdoc out_txt
216         cfg_enabled "$var" || return 0
217         [ -x scripts/mkman/mkman ] || { printf 'error: mkman not built\n' >&2; exit 1; }
218 
219         grep -qE '!man|\?man' "$src" || return 0
220 
221-        base=${src##*/}; base=${base%.c}
222         sec=$(man_section "$src")
223 
224         mkdir -p "man/man${sec}"
225-        out_mdoc="man/man${sec}/${base}.${sec}"
226-        out_txt="man/man${sec}/${base}.${sec}.txt"
227-        if any_newer_than "$out_mdoc" "$src" config.mk scripts/mkman/mkman; then
228+        out_mdoc="man/man${sec}/${name}.${sec}"
229+        out_txt="man/man${sec}/${name}.${sec}.txt"
230+        if any_newer_than "$out_mdoc" "$src" scripts/mk/config.kv scripts/mkman/mkman; then
231                 printf '  MAN   %s\n' "$out_mdoc"
232-                scripts/mkman/mkman -fmt mdoc -config config.mk -section "$sec" "$src" > "$out_mdoc"
233+                scripts/mkman/mkman -fmt mdoc -config scripts/mk/config.kv -section "$sec" "$src" > "$out_mdoc"
234         fi
235-        if any_newer_than "$out_txt" "$src" config.mk scripts/mkman/mkman; then
236+        if any_newer_than "$out_txt" "$src" scripts/mk/config.kv scripts/mkman/mkman; then
237                 printf '  MAN   %s\n' "$out_txt"
238-                scripts/mkman/mkman -fmt txt -config config.mk -section "$sec" "$src" > "$out_txt"
239+                scripts/mkman/mkman -fmt txt -config scripts/mk/config.kv -section "$sec" "$src" > "$out_txt"
240         fi
241 }
242 
243 build_man() {
244-        local dir cat src base
245+        local src cat base sub name var
246         if [ ! -x scripts/mkman/mkman ] || any_newer_than scripts/mkman/mkman scripts/mkman/main.go scripts/mkman/page.go scripts/mkman/parse.go scripts/mkman/mdoc.go; then
247                 printf '  GO    scripts/mkman/mkman\n'
248                 (cd scripts/mkman && go build -o mkman .)
249         fi
250-        for dir in cmd/*; do
251-                [ -d "$dir" ] || continue
252-                cat=${dir##*/}
253-                for src in "$dir"/*.c; do
254-                        [ -f "$src" ] || continue
255-                        base=${src##*/}; base=${base%.c}
256-                        build_man_for "$(cfgvar "$cat" "$base")" "$src"
257-                done
258+        find cmd -type f -name '*.c' | while read -r src; do
259+                sub=${src#cmd/}
260+                cat=${sub%%/*}
261+                base=${src##*/}
262+                base=${base%.c}
263+                name=${sub#*/}
264+                if [ "${name}" != "${base}.c" ]; then
265+                        name=${name%%/*}
266+                else
267+                        name=$base
268+                fi
269+                var=$(cfgvar "$cat" "$name")
270+                build_man_for "$var" "$src" "$name"
271         done
272 }
273 
274@@ -515,6 +511,61 @@ do_install() {
275         done
276 }
277 
278+do_regen() {
279+        # 1. regenerate config
280+        sh scripts/genconfig.sh
281+
282+        # 2. re-read the new config.kv
283+        if [ -f scripts/mk/config.kv ]; then
284+                # shellcheck disable=SC1091
285+                . scripts/mk/config.kv
286+        fi
287+
288+        # 3. clean the generated files to force regeneration
289+        rm -f cmd/posix/getconf.h cmd/posix/bc.c cmd/posix/bc.h
290+        rm -f cmd/posix/awk/awkgram.tab.c cmd/posix/awk/awkgram.tab.h cmd/posix/awk/proctab.c cmd/posix/awk/maketab
291+        rm -f cmd/posix/sh/mknodes cmd/posix/sh/mksyntax cmd/posix/sh/token.h cmd/posix/sh/syntax.c cmd/posix/sh/syntax.h cmd/posix/sh/nodes.c cmd/posix/sh/nodes.h cmd/posix/sh/builtins.c cmd/posix/sh/builtins.h
292+
293+        # 4. run the generation steps
294+        # for getconf.h
295+        printf '  GEN   cmd/posix/getconf.h\n'
296+        scripts/getconf.sh > cmd/posix/getconf.h || { rm -f cmd/posix/getconf.h; exit 1; }
297+
298+        # for bc.c from bc.y
299+        printf '  GEN   cmd/posix/bc.c\n'
300+        if command -v yacc >/dev/null 2>&1; then
301+                yacc -o cmd/posix/bc.c cmd/posix/bc.y
302+        elif command -v bison >/dev/null 2>&1; then
303+                bison -o cmd/posix/bc.c cmd/posix/bc.y
304+        fi
305+
306+        # for awk
307+        local adir=cmd/posix/awk
308+        if command -v yacc >/dev/null 2>&1; then
309+                yacc -d -o "$adir/awkgram.tab.c" "$adir/awkgram.y"
310+                if [ ! -f "$adir/awkgram.tab.h" ]; then
311+                        if [ -f y.tab.h ]; then
312+                                mv y.tab.h "$adir/awkgram.tab.h"
313+                        elif [ -f "$adir/y.tab.h" ]; then
314+                                mv "$adir/y.tab.h" "$adir/awkgram.tab.h"
315+                        fi
316+                fi
317+        elif command -v bison >/dev/null 2>&1; then
318+                bison -d -o "$adir/awkgram.tab.c" "$adir/awkgram.y"
319+        fi
320+        eval "$CC $CFLAGS -o $adir/maketab $adir/maketab.c"
321+        "$adir/maketab" "$adir/awkgram.tab.h" > "$adir/proctab.c"
322+
323+        # for sh
324+        local sdir=cmd/posix/sh
325+        eval "$CC $CFLAGS -o $sdir/mknodes $sdir/mknodes.c"
326+        eval "$CC $CPPFLAGS -I$sdir $CFLAGS -o $sdir/mksyntax $sdir/mksyntax.c"
327+        (cd "$sdir" && sh mktokens)
328+        (cd "$sdir" && ./mksyntax)
329+        (cd "$sdir" && ./mknodes nodetypes nodes.c.pat)
330+        (cd "$sdir" && sh mkbuiltins .)
331+}
332+
333 do_clean() {
334         printf '  CLEAN object files\n'
335         find shared cmd -name '*.o' -exec rm -f {} +
336@@ -562,11 +613,42 @@ case "$TARGET" in
337         make)            build_lib; build_make ;;
338         linux|net|xsi|pseudo|extra)
339                          build_lib; build_simple_tools "$TARGET" ;;
340-        man)             build_man ;;
341-        install)         do_install ;;
342+        regen)           do_regen ;;
343         clean)           do_clean ;;
344+        man)             build_man ;;
345+        install)
346+                build_lib
347+                build_posix
348+                build_dev
349+                build_simple_tools linux
350+                build_simple_tools net
351+                build_simple_tools xsi
352+                build_simple_tools pseudo
353+                build_simple_tools extra
354+                build_man
355+                do_install
356+                ;;
357+        help)
358+                printf 'usage: sh Makefile.sh [-jN] [-lN] [all|clean|install|man|lib|posix|linux|net|xsi|pseudo|extra|dev|make|regen|help]\n'
359+                printf '\nTargets:\n'
360+                printf '  all       Build all enabled utilities\n'
361+                printf '  clean     Clean built objects and binaries\n'
362+                printf '  install   Install binaries and man pages\n'
363+                printf '  man       Generate man pages\n'
364+                printf '  lib       Build core libraries\n'
365+                printf '  posix     Build POSIX utilities\n'
366+                printf '  linux     Build Linux utilities\n'
367+                printf '  net       Build Network utilities\n'
368+                printf '  xsi       Build XSI utilities\n'
369+                printf '  pseudo    Build Pseudo utilities\n'
370+                printf '  extra     Build Extra utilities\n'
371+                printf '  dev       Build Dev toolchain\n'
372+                printf '  make      Build POSIX make\n'
373+                printf '  regen     Regenerate configuration and all generated source files\n'
374+                printf '  help      Show this help message\n'
375+                ;;
376         *)
377-                printf 'usage: sh Makefile.sh [-jN] [-lN] [all|clean|install|man|lib|posix|linux|net|xsi|pseudo|extra|dev|make]\n' >&2
378+                printf 'usage: sh Makefile.sh [-jN] [-lN] [all|clean|install|man|lib|posix|linux|net|xsi|pseudo|extra|dev|make|regen|help]\n' >&2
379                 exit 1
380                 ;;
381 esac
M README
+35, -26
 1@@ -6,6 +6,11 @@ complete SBASE & UBASE., new utils partially based on toybox have
 2 been added, specifically, the utils under cmd/net are partially based
 3 on their toybox applet equivalent.
 4 
 5+The codebase has diverged a lot since the project started. And we have
 6+a myriad of utilities which were written specifically for ARUU.
 7+We also have greatly simplified ports of components from other systems
 8+and projects, such as FreeBSD sh, minix yap (pager), onetrueawk, etc.
 9+
10 OVERVIEW
11 ========
12 
13@@ -64,7 +69,6 @@ INSTALL
14 SOURCE LAYOUT
15 =============
16 
17-    config.mk              build configuration
18     Makefile               pdpmake-compatible build rules
19     scripts/
20       mkbox                builds aruu-box from compiled tool objects
21@@ -74,48 +78,53 @@ SOURCE LAYOUT
22       libutil/             utility library (eprintf, ealloc, recurse, ...)
23       libutf/              UTF-8/rune library
24     cmd/
25-      posix/               POSIX.1-2008 tools (sh, make, grep, sed, pax, ...)
26-      linux/               Linux-specific tools (mount, dmesg, insmod, ...)
27-      net/                 networking tools (wget, ping, nc, ifconfig, ...)
28-      pseudo/              widely-used non-POSIX tools (tar, stat, seq, ...)
29-      xsi/                 XSI-extension tools (mknod, su, passwd)
30+      posix/          POSIX.1-2008 tools (sh, make, grep, sed, pax, ...)
31+      linux/          Linux-specific tools (mount, dmesg, insmod, ...)
32+      net/            networking tools (wget, ip, ping, nc, ...)
33+      pseudo/         widely-used non-POSIX tools (tar, stat, seq, ...)
34+      xsi/            XSI-extension tools (mknod, su, passwd)
35+      extra/          third-party-flavored extras (yap, b3sum, fdisk, ...)
36+      dev/            small toolchain (as, cc, ld, ar); not built by
37+                      default, see PRESET_UTILS in build.cfg
38 
39 TOOLS
40 =====
41 
42 posix:
43-	[, awk, basename, cal, cat, chgrp, chmod, chown, cksum, cmp, comm, cp,
44-	cut, date, dd, df, dirname, du, echo, ed, env, expand, expr, false,
45-	find, fold, getconf, grep, head, id, join, kill, link, ln, logger,
46-	logname, ls, make, mesg, mkdir, mkfifo, mv, nice, nl, nohup, od,
47-	paste, pathchk, pax, printf, ps, pwd, readlink, renice, rm, rmdir,
48-	sed, sh, sleep, sort, split, tail, tee, test, time, touch, tr, true,
49-	tsort, tty, uname, unexpand, uniq, unlink, uudecode, uuencode, wc,
50-	who, xargs
51+	[, awk, basename, bc, cal, cat, chgrp, chmod, chown, cksum, cmp, comm,
52+	cp, cut, date, dd, df, diff, dirname, du, echo, ed, env, expand, expr,
53+	false, find, fold, getconf, grep, head, id, join, kill, link, ln,
54+	logger, logname, ls, make, mesg, mkdir, mkfifo, mv, nice, nl, nohup,
55+	od, paste, patch, pathchk, pax, printf, ps, pwd, readlink, renice, rm,
56+	rmdir, sed, sh, sleep, sort, split, tail, tee, test, time, touch, tr,
57+	true, tsort, tty, uname, unexpand, uniq, unlink, uudecode, uuencode,
58+	wc, who, xargs
59 
60 linux:
61-	blkdiscard, chvt, ctrlaltdel, dmesg, eject, fallocate, free,
62-	freeramdisk, fsfreeze, hwclock, insmod, lsmod, lsusb, mkswap, mount,
63-	mountpoint, pidof, pivot_root, pwdx, readahead, rmmod, swaplabel,
64-	swapoff, swapon, switch_root, sysctl, umount, unshare, uptime,
65-	vtallow
66+	blkdiscard, chvt, ctrlaltdel, depmod, eject, freeramdisk, fsfreeze,
67+	hwclock, insmod, lsmod, lsusb, mkswap, modprobe, mount, mountpoint,
68+	pivot_root, readahead, rmmod, swaplabel, swapoff, swapon, switch_root,
69+	sysctl, tunctl, umount, unshare, vtallow
70 
71 net:
72-	host, httpd, ifconfig, netcat, ping, sdhcp, tftp, tunctl, wget
73+	host, httpd, ifconfig, ip, netcat, ping, sdhcp, tftp, wget
74 
75 pseudo:
76-	base64, chroot, clear, cols, cron, flock, getty, halt, hostname,
77-	install, killall5, last, lastlog, login, md5sum, mktemp, nologin,
78-	pagesize, printenv, respawn, rev, seq, setsid, sha1sum, sha224sum,
79-	sha256sum, sha384sum, sha512-224sum, sha512-256sum, sha512sum, sponge,
80-	stat, tar, truncate, watch, which, whoami, xinstall, yes
81+	base64, chroot, clear, cols, cron, diff3, dmesg, fallocate, flock,
82+	free, getty, halt, hostname, install, killall5, last, lastlog, login,
83+	md5sum, mkpasswd, mktemp, nologin, pagesize, pidof, printenv, pwdx,
84+	respawn, rev, seq, setsid, sha1sum, sha224sum, sha256sum, sha384sum,
85+	sha512-224sum, sha512-256sum, sha512sum, sponge, stat, tar, truncate,
86+	uptime, watch, which, whoami, xinstall, yes
87 
88 xsi:
89 	mknod, passwd, su
90 
91+extra:
92+	b3sum, blkid, fdisk, lsblk, sync, yap
93+
94 TODOs / PENDING RELEASE
95 =======================
96-ip - new impl partially based on toybox's applet
97 init - situation/sctl rewrite
98 troff - neatroff
99 man - unsure
+60, -4
  1@@ -1,8 +1,8 @@
  2 # posix: POSIX 2024
  3 PRESET_FEATURES=all
  4 
  5-# subset  of: posix xsi net pseudo linux dev
  6-PRESET_UTILS="posix xsi net pseudo linux"
  7+# subset  of: posix xsi net pseudo extra linux dev
  8+PRESET_UTILS="posix xsi net pseudo extra linux"
  9 
 10 # installation paths
 11 VERSION=2026-06-08T05-53-UTC-03
 12@@ -135,7 +135,7 @@ all)
 13 esac
 14 
 15 
 16-BUILD_POSIX=0; BUILD_XSI=0; BUILD_PSEUDO=0; BUILD_NET=0; BUILD_LINUX=0; BUILD_DEV=0
 17+BUILD_POSIX=0; BUILD_XSI=0; BUILD_PSEUDO=0; BUILD_NET=0; BUILD_LINUX=0; BUILD_EXTRA=0; BUILD_DEV=0
 18 for _p in $PRESET_UTILS; do
 19     case "$_p" in
 20         posix)  BUILD_POSIX=1  ;;
 21@@ -143,6 +143,7 @@ for _p in $PRESET_UTILS; do
 22         net)    BUILD_NET=1    ;;
 23         xsi)    BUILD_XSI=1    ;;
 24         pseudo) BUILD_PSEUDO=1 ;;
 25+        extra)  BUILD_EXTRA=1  ;;
 26         dev)    BUILD_DEV=1    ;;
 27         *)
 28             printf 'build.cfg: unknown util preset: %s\n' "$_p" >&2
 29@@ -156,13 +157,39 @@ unset _p
 30 # BUILD_POSIX_SH=0       # disable a tool when its group is active
 31 # BUILD_DEV_AS=1         # enable a tool whose group isnt in PRESET_UTILS
 32 FEATURE_SH_HISTEDIT=1
 33+
 34+# FEATURE_INPROC_EXEC: when set to 1, wexecvp/wexecv/wpopen/wsystem call
 35+# registered tool mains directly instead of fork+exec. this is only meaningful
 36+# inside aruu-box, where every tool has registered its main at startup
 37+#
 38+# the analogy is busybox: a single binary where sh can call grep, sed, awk, etc.
 39+# without spawning a new process for each one. scripts run faster and the whole
 40+# system needs no external PATH at all. aruu-box built with this flag is fully
 41+# self-contained, exactly like a busybox applet collection
 42+#
 43+# this is optional. set to 0 to build the box without inproc dispatch (each
 44+# tool call still fork+execs). for individual standalone tool binaries this
 45+# flag has no practical effect because no other mains are registered
 46+#
 47 FEATURE_INPROC_EXEC=0
 48+#
 49+# FEATURE_INPROC_EXEC_OVERRIDE: only meaningful when FEATURE_INPROC_EXEC=1
 50+# when set to 1, ARUU_INPROC_EXEC=0 in the environment forces fork+exec at
 51+# runtime, letting a person reach an external tool that shares a name with
 52+# a builtin without giving its full path. when set to 0, that env var is
 53+# never read at all and inproc dispatch cannot be bypassed except by a tool
 54+# explicitly calling wexec_set_inproc()
 55+#
 56+FEATURE_INPROC_EXEC_OVERRIDE=0
 57+#
 58+
 59 # tls backend: set exactly one to 1 to enable tls
 60+#
 61 FEATURE_USE_BEARSSL=0
 62 FEATURE_USE_LIBRESSL=0
 63 FEATURE_USE_OPENSSL=0
 64 FEATURE_USE_SSL=1
 65-
 66+#
 67 if [ "$FEATURE_USE_SSL" = 1 ]; then
 68     if [ "$FEATURE_USE_BEARSSL" = 0 ] && [ "$FEATURE_USE_LIBRESSL" = 0 ] && [ "$FEATURE_USE_OPENSSL" = 0 ]; then
 69         if pkg-config --exists libbearssl 2>/dev/null || pkg-config --exists bearssl 2>/dev/null; then
 70@@ -174,3 +201,32 @@ if [ "$FEATURE_USE_SSL" = 1 ]; then
 71         fi
 72     fi
 73 fi
 74+# auto-detect TLS/SSL flags based on selected backend
 75+CPPFLAGS_TLS="" LDFLAGS_TLS="" LDLIBS_TLS="" PKG_NAME=""
 76+if [ "$FEATURE_USE_BEARSSL" = 1 ]; then
 77+    if pkg-config --exists libbearssl 2>/dev/null; then
 78+        PKG_NAME="libbearssl"
 79+    elif pkg-config --exists bearssl 2>/dev/null; then
 80+        PKG_NAME="bearssl"
 81+    fi
 82+elif [ "$FEATURE_USE_LIBRESSL" = 1 ]; then
 83+    if pkg-config --exists libtls 2>/dev/null; then
 84+        PKG_NAME="libtls"
 85+    else
 86+        LDLIBS_TLS="-ltls"
 87+    fi
 88+elif [ "$FEATURE_USE_OPENSSL" = 1 ]; then
 89+    if pkg-config --exists openssl 2>/dev/null; then
 90+        PKG_NAME="openssl"
 91+    else
 92+        LDLIBS_TLS="-lssl -lcrypto"
 93+    fi
 94+fi
 95+if [ -n "$PKG_NAME" ]; then
 96+    CPPFLAGS_TLS="$(pkg-config --cflags "$PKG_NAME")"
 97+    LDLIBS_TLS="$(pkg-config --libs "$PKG_NAME")"
 98+fi
 99+# trim whitespace
100+CPPFLAGS_TLS=$(echo "$CPPFLAGS_TLS" | xargs)
101+LDFLAGS_TLS=$(echo "$LDFLAGS_TLS" | xargs)
102+LDLIBS_TLS=$(echo "$LDLIBS_TLS" | xargs)
+48, -1
 1@@ -49,6 +49,7 @@
 2  */
 3 
 4 #include "../../../shared/paths.h"
 5+#include "../../../shared/wexec.h"
 6 #include "alias.h"
 7 #include "builtins.h"
 8 #include "error.h"
 9@@ -102,6 +103,23 @@ shellexec(char **argv, char **envp, const char *path, int idx)
10   const char *opt;
11   int         e;
12 
13+#if FEATURE_INPROC_EXEC
14+  {
15+    /* basename of argv[0] for slash-free lookup */
16+    const char *base = strrchr(argv[0], '/');
17+    base = base ? base + 1 : argv[0];
18+    if (wexec_get_inproc() && wexec_is_builtin(base)) {
19+      int ret;
20+      fflush(stdout);
21+      fflush(stderr);
22+      ret = wexecvp(base, argv);
23+      fflush(stdout);
24+      fflush(stderr);
25+      _exit(ret);
26+    }
27+  }
28+#endif
29+
30   if (strchr(argv[0], '/') != NULL) {
31     tryexec(argv[0], argv, envp);
32     e = errno;
33@@ -313,6 +331,10 @@ printentry(struct tblentry *cmdp, int verbose)
34       ckfree(name);
35       INTON;
36     }
37+#if FEATURE_INPROC_EXEC
38+  } else if (cmdp->cmdtype == CMDWEXEC) {
39+    out1fmt("inproc %s", cmdp->cmdname);
40+#endif
41 #ifdef DEBUG
42   } else {
43     error("internal error: cmdtype %d", cmdp->cmdtype);
44@@ -357,7 +379,7 @@ find_command(const char *name, struct cmdentry *entry, int act, const char *path
45       goto success;
46   }
47 
48-  /* Check for builtin next */
49+  /* check for builtin next */
50   if ((i = find_builtin(name, &spec)) >= 0) {
51     INTOFF;
52     cmdp = cmdlookup(name, 1);
53@@ -370,6 +392,22 @@ find_command(const char *name, struct cmdentry *entry, int act, const char *path
54     goto success;
55   }
56 
57+#if FEATURE_INPROC_EXEC
58+  /* when inproc dispatch is active, registered wexec builtins are available
59+   * even if they are not present on the filesystem */
60+  if (wexec_get_inproc() && wexec_is_builtin(name)) {
61+    INTOFF;
62+    cmdp = cmdlookup(name, 1);
63+    if (cmdp->cmdtype == CMDFUNCTION)
64+      cmdp = &loc_cmd;
65+    cmdp->cmdtype     = CMDWEXEC;
66+    cmdp->param.index = 0;
67+    cmdp->special     = 0;
68+    INTON;
69+    goto success;
70+  }
71+#endif
72+
73   /* We have to search path. */
74 
75   e   = ENOENT;
76@@ -783,6 +821,15 @@ typecmd_impl(int argc, char **argv, int cmd, const char *path)
77           out1fmt("%s is a shell builtin\n", argv[i]);
78         break;
79 
80+#if FEATURE_INPROC_EXEC
81+      case CMDWEXEC:
82+        if (cmd == TYPECMD_SMALLV)
83+          out1fmt("%s\n", argv[i]);
84+        else
85+          out1fmt("%s is an inproc builtin\n", argv[i]);
86+        break;
87+#endif
88+
89       default:
90         if (cmd != TYPECMD_SMALLV)
91           outfmt(out2, "%s: not found\n", argv[i]);
+1, -0
1@@ -39,6 +39,7 @@
2 #define CMDNORMAL   0  /* command is an executable program */
3 #define CMDBUILTIN  1  /* command is a shell builtin */
4 #define CMDFUNCTION 2  /* command is a shell function */
5+#define CMDWEXEC    3  /* command is a registered inproc builtin */
6 
7 /* values for typecmd_impl's third parameter */
8 enum {
+9, -8
 1@@ -46,14 +46,15 @@ feature_setvar=1
 2 feature_wordexp=1
 3 feature_easter=1
 4 
 5-if [ -f ../../config.mk ]; then
 6-	feature_histedit=$(grep '^[[:space:]]*FEATURE_SH_HISTEDIT[[:space:]]*=' ../../config.mk | cut -d= -f2 | tr -d '[:space:]')
 7-	feature_local=$(grep '^[[:space:]]*FEATURE_SH_LOCAL[[:space:]]*=' ../../config.mk | cut -d= -f2 | tr -d '[:space:]')
 8-	feature_let=$(grep '^[[:space:]]*FEATURE_SH_LET[[:space:]]*=' ../../config.mk | cut -d= -f2 | tr -d '[:space:]')
 9-	feature_ulimit=$(grep '^[[:space:]]*FEATURE_SH_ULIMIT[[:space:]]*=' ../../config.mk | cut -d= -f2 | tr -d '[:space:]')
10-	feature_setvar=$(grep '^[[:space:]]*FEATURE_SH_SETVAR[[:space:]]*=' ../../config.mk | cut -d= -f2 | tr -d '[:space:]')
11-	feature_wordexp=$(grep '^[[:space:]]*FEATURE_SH_WORDEXP[[:space:]]*=' ../../config.mk | cut -d= -f2 | tr -d '[:space:]')
12-	feature_easter=$(grep '^[[:space:]]*FEATURE_SH_EASTER[[:space:]]*=' ../../config.mk | cut -d= -f2 | tr -d '[:space:]')
13+if [ -f ../../../scripts/mk/config.kv ]; then
14+	. ../../../scripts/mk/config.kv
15+	feature_histedit=$FEATURE_SH_HISTEDIT
16+	feature_local=$FEATURE_SH_LOCAL
17+	feature_let=$FEATURE_SH_LET
18+	feature_ulimit=$FEATURE_SH_ULIMIT
19+	feature_setvar=$FEATURE_SH_SETVAR
20+	feature_wordexp=$FEATURE_SH_WORDEXP
21+	feature_easter=$FEATURE_SH_EASTER
22 fi
23 
24 exec > builtins.c
R cmd/posix/diff3.c => cmd/pseudo/diff3.c
+1, -2
 1@@ -420,8 +420,7 @@ main(int argc, char *argv[])
 2       iflag = 1;
 3       break;
 4     case 'L':
 5-      // ?man -L:label: use label in place of file name in merge
 6-      // output
 7+      // ?man -L:label: use label in place of file name in merge output
 8       if (nlabels >= 3)
 9         usage();
10       labels[nlabels++] = EARGF(usage());
+89, -74
  1@@ -1,72 +1,72 @@
  2 /* See LICENSE file for copyright and license details. */
  3-
  4-#include <sys/stat.h>
  5-#include <sys/types.h>
  6+#include "wexec.h"
  7+#include "util.h"
  8+#include "arg.h"
  9 
 10 #include <fcntl.h>
 11 #include <limits.h>
 12 #include <stdio.h>
 13 #include <stdlib.h>
 14 #include <string.h>
 15+#include <sys/stat.h>
 16+#include <sys/types.h>
 17 #include <unistd.h>
 18 
 19-#include "util.h"
 20-
 21 static int aflag;
 22 
 23 static int
 24 canexec(int fd, const char *name)
 25 {
 26-  struct stat st;
 27+	struct stat st;
 28 
 29-  if (fstatat(fd, name, &st, 0) < 0 || !S_ISREG(st.st_mode))
 30-    return 0;
 31-  return faccessat(fd, name, X_OK, AT_EACCESS) == 0;
 32+	if (fstatat(fd, name, &st, 0) < 0 || !S_ISREG(st.st_mode))
 33+		return 0;
 34+	return faccessat(fd, name, X_OK, AT_EACCESS) == 0;
 35 }
 36 
 37 static int
 38 which(const char *path, const char *name)
 39 {
 40-  char  *ptr, *p;
 41-  size_t i, len;
 42-  int    dirfd, found = 0;
 43-
 44-  if (strchr(name, '/')) {
 45-    found = canexec(AT_FDCWD, name);
 46-    if (found)
 47-      puts(name);
 48-    return found;
 49-  }
 50-
 51-  ptr = p = enstrdup(3, path);
 52-  len     = strlen(p);
 53-  for (i = 0; i < len + 1; i++) {
 54-    if (ptr[i] != ':' && ptr[i] != '\0')
 55-      continue;
 56-    ptr[i] = '\0';
 57-    if ((dirfd = open(p, O_RDONLY)) >= 0) {
 58-      if (canexec(dirfd, name)) {
 59-        found = 1;
 60-        fputs(p, stdout);
 61-        if (i && ptr[i - 1] != '/')
 62-          fputc('/', stdout);
 63-        puts(name);
 64-      }
 65-      close(dirfd);
 66-      if (!aflag && found)
 67-        break;
 68-    }
 69-    p = ptr + i + 1;
 70-  }
 71-  free(ptr);
 72-
 73-  return found;
 74+	char  *ptr, *p;
 75+	size_t i, len;
 76+	int    dirfd, found = 0;
 77+
 78+	if (strchr(name, '/')) {
 79+		found = canexec(AT_FDCWD, name);
 80+		if (found)
 81+			puts(name);
 82+		return found;
 83+	}
 84+
 85+	ptr = p = enstrdup(3, path);
 86+	len     = strlen(p);
 87+	for (i = 0; i < len + 1; i++) {
 88+		if (ptr[i] != ':' && ptr[i] != '\0')
 89+			continue;
 90+		ptr[i] = '\0';
 91+		if ((dirfd = open(p, O_RDONLY)) >= 0) {
 92+			if (canexec(dirfd, name)) {
 93+				found = 1;
 94+				fputs(p, stdout);
 95+				if (i && ptr[i - 1] != '/')
 96+					fputc('/', stdout);
 97+				puts(name);
 98+			}
 99+			close(dirfd);
100+			if (!aflag && found)
101+				break;
102+		}
103+		p = ptr + i + 1;
104+	}
105+	free(ptr);
106+
107+	return found;
108 }
109 
110 static void
111 usage(void)
112 {
113-  eprintf("usage: %s [-a] name ...\n", argv0);
114+	eprintf("usage: %s [-a] name ...\n", argv0);
115 }
116 
117 // ?man which: locate a command
118@@ -75,34 +75,49 @@ usage(void)
119 int
120 main(int argc, char *argv[])
121 {
122-  char *path;
123-  int   found = 0, foundall = 1;
124-
125-  ARGBEGIN
126-  {
127-    // ?man -a: print or show all entries
128-    case 'a':
129-      aflag = 1;
130-      break;
131-    default:
132-      usage();
133-  }
134-  ARGEND
135-
136-  if (!argc)
137-    usage();
138-
139-  if (!(path = getenv("PATH")))
140-    enprintf(3, "$PATH is not set\n");
141-
142-  for (; *argv; argc--, argv++) {
143-    if (which(path, *argv)) {
144-      found = 1;
145-    } else {
146-      weprintf("%s: not an external command\n", *argv);
147-      foundall = 0;
148-    }
149-  }
150-
151-  return found ? foundall ? 0 : 1 : 2;
152+	char *path;
153+	int   found = 0, foundall = 1;
154+
155+	ARGBEGIN {
156+	// ?man -a: print or show all entries
157+	case 'a':
158+		aflag = 1;
159+		break;
160+	default:
161+		usage();
162+	} ARGEND
163+
164+	if (!argc)
165+		usage();
166+
167+	if (!(path = getenv("PATH")))
168+		enprintf(3, "$PATH is not set\n");
169+
170+	for (; *argv; argc--, argv++) {
171+#if FEATURE_INPROC_EXEC
172+		/* inproc builtins are function pointers with no filesystem path */
173+		if (wexec_get_inproc() && wexec_is_builtin(*argv)) {
174+			printf("%s: inproc builtin\n", *argv);
175+			found = 1;
176+			if (!aflag)
177+				continue;
178+		}
179+#endif
180+		if (which(path, *argv)) {
181+			found = 1;
182+		} else {
183+#if FEATURE_INPROC_EXEC
184+			/* already reported above when inproc was active */
185+			if (!wexec_get_inproc() || !wexec_is_builtin(*argv))
186+#endif
187+			{
188+				weprintf("%s: not an external command\n", *argv);
189+				foundall = 0;
190+			}
191+		}
192+	}
193+
194+	if (fshut(stdout, "<stdout>"))
195+		return 2;
196+	return found ? foundall ? 0 : 1 : 2;
197 }
+98, -0
 1@@ -0,0 +1,98 @@
 2+#!/bin/sh
 3+# https://srcdump.net/shrub/shrubtools/tree/main/item/deps.html
 4+#
 5+# emit makefile dependencies for a list of C sources using the compiler's .d output. having a bunch of
 6+# autogenerated .d files and -include's is flaky and ugly, and might not work on all make
 7+# implementations. this way you can generate the deps once and ship the makefile.
 8+# it takes a list of files from stdin and prints to stdout. you might also want to append
 9+# you CFLAGS/CPPFLAGS if that will change the deps.
10+#
11+# example:
12+#     find . -type f -name '*.c' | CPPFLAGS='-Iinclude' deps >> Makefile
13+#
14+set -eu
15+
16+cc=${CC:-cc}
17+cppflags=${CPPFLAGS:-}
18+cflags=${CFLAGS:-}
19+tmpbase=${TMPDIR:-/tmp}
20+
21+cleanup() {
22+	rm -rf "$tmpdir"
23+}
24+
25+usage() {
26+	printf 'usage: %s [file.c ...]\n' "${0##*/}" >&2
27+	printf '       %s < file-list\n' "${0##*/}" >&2
28+	exit 2
29+}
30+
31+list() {
32+	if [ "$#" -gt 0 ]; then
33+		for src do
34+			case $src in
35+			*.c) printf '%s\n' "$src" ;;
36+			*) printf '%s: not a .c file: %s\n' "${0##*/}" "$src" >&2; exit 2 ;;
37+			esac
38+		done
39+		return
40+	fi
41+
42+	while IFS= read -r src; do
43+		[ -n "$src" ] || continue
44+		case $src in
45+		*.c) printf '%s\n' "$src" ;;
46+		*) printf '%s: not a .c file: %s\n' "${0##*/}" "$src" >&2; exit 2 ;;
47+		esac
48+	done
49+}
50+
51+if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then
52+	usage
53+fi
54+
55+tmpdir=$(mktemp -d "$tmpbase/deps.XXXXXX")
56+trap cleanup EXIT HUP INT TERM
57+
58+count=0
59+srcs=$tmpdir/sources
60+list "$@" > "$srcs"
61+
62+if [ ! -s "$srcs" ]; then
63+	printf '%s: no .c files provided\n' "${0##*/}" >&2
64+	exit 1
65+fi
66+
67+printf '\n'
68+printf '#AUTOGENERATED\n'
69+
70+while IFS= read -r src; do
71+	dep=$tmpdir/$count.d
72+	obj=${src%.c}.o
73+	"$cc" $cppflags $cflags -MMD -MF "$dep" -MT "$obj" -E -o /dev/null "$src"
74+	#flatten the block with one target: dep line per prereq
75+	awk '
76+	BEGIN {
77+		rule = ""
78+	}
79+	{
80+		line = $0
81+		sub(/\\$/, "", line)
82+		rule = rule line " "
83+		if ($0 !~ /\\$/) {
84+			sub(/^[[:space:]]*/, "", rule)
85+			split(rule, parts, ":")
86+			target = parts[1]
87+			deps = substr(rule, length(target) + 2)
88+			n = split(deps, items, /[[:space:]]+/)
89+			for (i = 1; i <= n; ++i) {
90+				if (items[i] == "")
91+					continue
92+				print target ": " items[i]
93+			}
94+			rule = ""
95+		}
96+	}
97+	' "$dep"
98+	count=$((count + 1))
99+done < "$srcs"
+156, -0
  1@@ -0,0 +1,156 @@
  2+#!/bin/sh
  3+# genconfig.sh - generate config.mk and config.kv from build.cfg
  4+
  5+set -e
  6+
  7+# load build.cfg
  8+if [ -f build.cfg ]; then
  9+        . ./build.cfg
 10+else
 11+        echo "genconfig: build.cfg not found" >&2
 12+        exit 1
 13+fi
 14+
 15+mkdir -p scripts/mk
 16+
 17+mk_file="scripts/mk/config.mk"
 18+kv_file="scripts/mk/config.kv"
 19+
 20+# clear existing files
 21+: > "${mk_file}"
 22+: > "${kv_file}"
 23+
 24+# write version prefix manprefix
 25+echo "VERSION = ${VERSION}" >> "${mk_file}"
 26+echo "VERSION=\"${VERSION}\"" >> "${kv_file}"
 27+
 28+echo "PREFIX = ${PREFIX}" >> "${mk_file}"
 29+echo "PREFIX=\"${PREFIX}\"" >> "${kv_file}"
 30+
 31+# default manprefix to prefix/share/man if empty
 32+man_pref="${MANPREFIX:-/usr/local/share/man}"
 33+echo "MANPREFIX = ${man_pref}" >> "${mk_file}"
 34+echo "MANPREFIX=\"${man_pref}\"" >> "${kv_file}"
 35+
 36+# toolchain defaults
 37+echo "RANLIB = ${RANLIB:-ranlib}" >> "${mk_file}"
 38+echo "RANLIB=\"${RANLIB:-ranlib}\"" >> "${kv_file}"
 39+
 40+echo "AR = ${AR:-ar}" >> "${mk_file}"
 41+echo "AR=\"${AR:-ar}\"" >> "${kv_file}"
 42+
 43+echo "ARFLAGS = ${ARFLAGS:-rc}" >> "${mk_file}"
 44+echo "ARFLAGS=\"${ARFLAGS:-rc}\"" >> "${kv_file}"
 45+
 46+# build toggles
 47+echo "" >> "${mk_file}"
 48+echo "# build toggles" >> "${mk_file}"
 49+for g in BUILD_POSIX BUILD_XSI BUILD_NET BUILD_PSEUDO BUILD_EXTRA BUILD_LINUX BUILD_DEV; do
 50+        eval "val=\${$g:-0}"
 51+        echo "$g = $val" >> "${mk_file}"
 52+        echo "$g=\"$val\"" >> "${kv_file}"
 53+done
 54+
 55+# dynamic tool discovery function
 56+list_tools() {
 57+        local catg="$1" dirs="" files="" d f b
 58+        # Find all subdirectories
 59+        for d in "cmd/$catg"/*; do
 60+                if [ -d "$d" ]; then
 61+                        dirs="$dirs ${d##*/}"
 62+                fi
 63+        done
 64+        # Find all .c and .y files
 65+        for f in "cmd/$catg"/*.c "cmd/$catg"/*.y; do
 66+                [ -f "$f" ] || continue
 67+                b=${f##*/}
 68+                b=${b%.c}
 69+                b=${b%.y}
 70+                case "$b" in
 71+                        # Exclude intermediate files or helper generators
 72+                        maketab|mknodes|mksyntax|y.tab|*gram.tab) continue ;;
 73+                esac
 74+                files="$files $b"
 75+        done
 76+
 77+        # Output sorted unique list of uppercase names
 78+        # shellcheck disable=SC2086
 79+        printf '%s %s\n' $dirs $files | tr ' ' '\n' | sort -u | tr 'a-z-' 'A-Z_' | grep -v '^$'
 80+}
 81+
 82+write_subtarget() {
 83+        group="$1"
 84+        tool="$2"
 85+        u_group=$(echo "$group" | tr '[:lower:]' '[:upper:]')
 86+        var_name="BUILD_${u_group}_${tool}"
 87+
 88+        eval "has_override=\${$var_name+yes}"
 89+        eval "val=\${$var_name:-}"
 90+
 91+        eval "group_val=\$BUILD_${u_group}"
 92+
 93+        if [ "$has_override" = "yes" ]; then
 94+                echo "${var_name} = ${val}" >> "${mk_file}"
 95+                echo "${var_name}=\"${val}\"" >> "${kv_file}"
 96+        else
 97+                echo "${var_name} = \$(BUILD_${u_group})" >> "${mk_file}"
 98+                echo "${var_name}=\"${group_val}\"" >> "${kv_file}"
 99+        fi
100+}
101+
102+# write subtargets for each category dynamically
103+for catg in posix xsi net pseudo extra linux dev; do
104+        echo "" >> "${mk_file}"
105+        echo "# ${catg} subtargets" >> "${mk_file}"
106+        tools=$(list_tools "$catg")
107+        for t in $tools; do
108+                write_subtarget "$catg" "$t"
109+        done
110+done
111+
112+# write feature flags
113+echo "" >> "${mk_file}"
114+echo "# feature flags" >> "${mk_file}"
115+features=$(set | grep '^FEATURE_[A-Za-z0-9_]*=' | cut -d= -f1 | sort)
116+for f in $features; do
117+        eval "val=\$$f"
118+        echo "$f = $val" >> "${mk_file}"
119+        echo "$f=\"$val\"" >> "${kv_file}"
120+done
121+
122+# write TLS variables to config files
123+echo "" >> "${mk_file}"
124+echo "CPPFLAGS_TLS = ${CPPFLAGS_TLS}" >> "${mk_file}"
125+echo "CPPFLAGS_TLS=\"${CPPFLAGS_TLS}\"" >> "${kv_file}"
126+
127+echo "LDFLAGS_TLS = ${LDFLAGS_TLS}" >> "${mk_file}"
128+echo "LDFLAGS_TLS=\"${LDFLAGS_TLS}\"" >> "${kv_file}"
129+
130+echo "LDLIBS_TLS = ${LDLIBS_TLS}" >> "${mk_file}"
131+echo "LDLIBS_TLS=\"${LDLIBS_TLS}\"" >> "${kv_file}"
132+
133+# write CPPFLAGS with all feature macros
134+echo "" >> "${mk_file}"
135+echo "CPPFLAGS =\\" >> "${mk_file}"
136+echo "        -Ishared\\" >> "${mk_file}"
137+echo "        -DPREFIX=\\\"\\\$(PREFIX)\\\"\\" >> "${mk_file}"
138+echo "        -D_DEFAULT_SOURCE\\" >> "${mk_file}"
139+echo "        -D_GNU_SOURCE\\" >> "${mk_file}"
140+echo "        -D_NETBSD_SOURCE\\" >> "${mk_file}"
141+echo "        -D_BSD_SOURCE\\" >> "${mk_file}"
142+echo "        -D_XOPEN_SOURCE=700\\" >> "${mk_file}"
143+echo "        -D_FILE_OFFSET_BITS=64\\" >> "${mk_file}"
144+for f in $features; do
145+        if [ "$f" = "FEATURE_USE_SSL" ]; then
146+                continue
147+        fi
148+        echo "        -D$f=\$($f)\\" >> "${mk_file}"
149+done
150+echo "        \$(CPPFLAGS_TLS)" >> "${mk_file}"
151+
152+# write toolchain configuration
153+echo "" >> "${mk_file}"
154+echo "CC = ${CC:-cc}" >> "${mk_file}"
155+echo "CFLAGS = ${CFLAGS:-}" >> "${mk_file}"
156+echo "LDFLAGS = ${LDFLAGS:-} \$(LDFLAGS_TLS)" >> "${mk_file}"
157+echo "LDLIBS = ${LDLIBS:-} \$(LDLIBS_TLS)" >> "${mk_file}"
+262, -0
  1@@ -0,0 +1,262 @@
  2+VERSION="2026-06-08T05-53-UTC-03"
  3+PREFIX="/usr/local"
  4+MANPREFIX="/usr/local/share/man"
  5+RANLIB="ranlib"
  6+AR="ar"
  7+ARFLAGS="rc"
  8+BUILD_POSIX="1"
  9+BUILD_XSI="1"
 10+BUILD_NET="1"
 11+BUILD_PSEUDO="1"
 12+BUILD_EXTRA="1"
 13+BUILD_LINUX="1"
 14+BUILD_DEV="0"
 15+BUILD_POSIX_AWK="1"
 16+BUILD_POSIX_BASENAME="1"
 17+BUILD_POSIX_BC="1"
 18+BUILD_POSIX_CAL="1"
 19+BUILD_POSIX_CAT="1"
 20+BUILD_POSIX_CHGRP="1"
 21+BUILD_POSIX_CHMOD="1"
 22+BUILD_POSIX_CHOWN="1"
 23+BUILD_POSIX_CKSUM="1"
 24+BUILD_POSIX_CMP="1"
 25+BUILD_POSIX_COMM="1"
 26+BUILD_POSIX_CP="1"
 27+BUILD_POSIX_CUT="1"
 28+BUILD_POSIX_DATE="1"
 29+BUILD_POSIX_DD="1"
 30+BUILD_POSIX_DF="1"
 31+BUILD_POSIX_DIFF="1"
 32+BUILD_POSIX_DIRNAME="1"
 33+BUILD_POSIX_DU="1"
 34+BUILD_POSIX_ECHO="1"
 35+BUILD_POSIX_ED="1"
 36+BUILD_POSIX_ENV="1"
 37+BUILD_POSIX_EXPAND="1"
 38+BUILD_POSIX_EXPR="1"
 39+BUILD_POSIX_FALSE="1"
 40+BUILD_POSIX_FIND="1"
 41+BUILD_POSIX_FOLD="1"
 42+BUILD_POSIX_GETCONF="1"
 43+BUILD_POSIX_GREP="1"
 44+BUILD_POSIX_HEAD="1"
 45+BUILD_POSIX_ID="1"
 46+BUILD_POSIX_JOIN="1"
 47+BUILD_POSIX_KILL="1"
 48+BUILD_POSIX_LINK="1"
 49+BUILD_POSIX_LN="1"
 50+BUILD_POSIX_LOGGER="1"
 51+BUILD_POSIX_LOGNAME="1"
 52+BUILD_POSIX_LS="1"
 53+BUILD_POSIX_MAKE="1"
 54+BUILD_POSIX_MESG="1"
 55+BUILD_POSIX_MKDIR="1"
 56+BUILD_POSIX_MKFIFO="1"
 57+BUILD_POSIX_MV="1"
 58+BUILD_POSIX_NICE="1"
 59+BUILD_POSIX_NL="1"
 60+BUILD_POSIX_NOHUP="1"
 61+BUILD_POSIX_OD="1"
 62+BUILD_POSIX_PASTE="1"
 63+BUILD_POSIX_PATCH="1"
 64+BUILD_POSIX_PATHCHK="1"
 65+BUILD_POSIX_PAX="1"
 66+BUILD_POSIX_PRINTF="1"
 67+BUILD_POSIX_PS="1"
 68+BUILD_POSIX_PWD="1"
 69+BUILD_POSIX_READLINK="1"
 70+BUILD_POSIX_RENICE="1"
 71+BUILD_POSIX_RM="1"
 72+BUILD_POSIX_RMDIR="1"
 73+BUILD_POSIX_SED="1"
 74+BUILD_POSIX_SH="1"
 75+BUILD_POSIX_SLEEP="1"
 76+BUILD_POSIX_SORT="1"
 77+BUILD_POSIX_SPLIT="1"
 78+BUILD_POSIX_TAIL="1"
 79+BUILD_POSIX_TEE="1"
 80+BUILD_POSIX_TEST="1"
 81+BUILD_POSIX_TIME="1"
 82+BUILD_POSIX_TOUCH="1"
 83+BUILD_POSIX_TR="1"
 84+BUILD_POSIX_TRUE="1"
 85+BUILD_POSIX_TSORT="1"
 86+BUILD_POSIX_TTY="1"
 87+BUILD_POSIX_UNAME="1"
 88+BUILD_POSIX_UNEXPAND="1"
 89+BUILD_POSIX_UNIQ="1"
 90+BUILD_POSIX_UNLINK="1"
 91+BUILD_POSIX_UUDECODE="1"
 92+BUILD_POSIX_UUENCODE="1"
 93+BUILD_POSIX_WC="1"
 94+BUILD_POSIX_WHO="1"
 95+BUILD_POSIX_XARGS="1"
 96+BUILD_XSI_MKNOD="1"
 97+BUILD_XSI_PASSWD="1"
 98+BUILD_XSI_SU="1"
 99+BUILD_NET_HOST="1"
100+BUILD_NET_HTTPD="1"
101+BUILD_NET_IFCONFIG="1"
102+BUILD_NET_IP="1"
103+BUILD_NET_NETCAT="1"
104+BUILD_NET_PING="1"
105+BUILD_NET_SDHCP="1"
106+BUILD_NET_TFTP="1"
107+BUILD_NET_WGET="1"
108+BUILD_PSEUDO_BASE64="1"
109+BUILD_PSEUDO_CHROOT="1"
110+BUILD_PSEUDO_CLEAR="1"
111+BUILD_PSEUDO_COLS="1"
112+BUILD_PSEUDO_CRON="1"
113+BUILD_PSEUDO_DIFF3="1"
114+BUILD_PSEUDO_DMESG="1"
115+BUILD_PSEUDO_FALLOCATE="1"
116+BUILD_PSEUDO_FLOCK="1"
117+BUILD_PSEUDO_FREE="1"
118+BUILD_PSEUDO_GETTY="1"
119+BUILD_PSEUDO_HALT="1"
120+BUILD_PSEUDO_HOSTNAME="1"
121+BUILD_PSEUDO_KILLALL5="1"
122+BUILD_PSEUDO_LAST="1"
123+BUILD_PSEUDO_LASTLOG="1"
124+BUILD_PSEUDO_LOGIN="1"
125+BUILD_PSEUDO_MD5SUM="1"
126+BUILD_PSEUDO_MKPASSWD="1"
127+BUILD_PSEUDO_MKTEMP="1"
128+BUILD_PSEUDO_NOLOGIN="1"
129+BUILD_PSEUDO_PAGESIZE="1"
130+BUILD_PSEUDO_PIDOF="1"
131+BUILD_PSEUDO_PRINTENV="1"
132+BUILD_PSEUDO_PWDX="1"
133+BUILD_PSEUDO_RESPAWN="1"
134+BUILD_PSEUDO_REV="1"
135+BUILD_PSEUDO_SEQ="1"
136+BUILD_PSEUDO_SETSID="1"
137+BUILD_PSEUDO_SHA1SUM="1"
138+BUILD_PSEUDO_SHA224SUM="1"
139+BUILD_PSEUDO_SHA256SUM="1"
140+BUILD_PSEUDO_SHA384SUM="1"
141+BUILD_PSEUDO_SHA512_224SUM="1"
142+BUILD_PSEUDO_SHA512_256SUM="1"
143+BUILD_PSEUDO_SHA512SUM="1"
144+BUILD_PSEUDO_SPONGE="1"
145+BUILD_PSEUDO_STAT="1"
146+BUILD_PSEUDO_TAR="1"
147+BUILD_PSEUDO_TRUNCATE="1"
148+BUILD_PSEUDO_UPTIME="1"
149+BUILD_PSEUDO_WATCH="1"
150+BUILD_PSEUDO_WHICH="1"
151+BUILD_PSEUDO_WHOAMI="1"
152+BUILD_PSEUDO_XINSTALL="1"
153+BUILD_PSEUDO_YES="1"
154+BUILD_EXTRA_B3SUM="1"
155+BUILD_EXTRA_BLKID="1"
156+BUILD_EXTRA_FDISK="1"
157+BUILD_EXTRA_LSBLK="1"
158+BUILD_EXTRA_SYNC="1"
159+BUILD_EXTRA_YAP="1"
160+BUILD_LINUX_BLKDISCARD="1"
161+BUILD_LINUX_CHVT="1"
162+BUILD_LINUX_CTRLALTDEL="1"
163+BUILD_LINUX_DEPMOD="1"
164+BUILD_LINUX_EJECT="1"
165+BUILD_LINUX_FREERAMDISK="1"
166+BUILD_LINUX_FSFREEZE="1"
167+BUILD_LINUX_HWCLOCK="1"
168+BUILD_LINUX_INSMOD="1"
169+BUILD_LINUX_LSMOD="1"
170+BUILD_LINUX_LSUSB="1"
171+BUILD_LINUX_MKSWAP="1"
172+BUILD_LINUX_MODPROBE="1"
173+BUILD_LINUX_MOUNT="1"
174+BUILD_LINUX_MOUNTPOINT="1"
175+BUILD_LINUX_PIVOT_ROOT="1"
176+BUILD_LINUX_READAHEAD="1"
177+BUILD_LINUX_RMMOD="1"
178+BUILD_LINUX_SWAPLABEL="1"
179+BUILD_LINUX_SWAPOFF="1"
180+BUILD_LINUX_SWAPON="1"
181+BUILD_LINUX_SWITCH_ROOT="1"
182+BUILD_LINUX_SYSCTL="1"
183+BUILD_LINUX_TUNCTL="1"
184+BUILD_LINUX_UMOUNT="1"
185+BUILD_LINUX_UNSHARE="1"
186+BUILD_LINUX_VTALLOW="1"
187+BUILD_DEV_AR="0"
188+BUILD_DEV_AS="0"
189+BUILD_DEV_CC="0"
190+BUILD_DEV_LD="0"
191+BUILD_DEV_SCRATCHPAD="0"
192+BUILD_DEV_XCUTIL="0"
193+FEATURE_CAL_EXT="1"
194+FEATURE_DEPMOD_ALIAS="1"
195+FEATURE_DEPMOD_SYMBOLS="1"
196+FEATURE_DIFF3_EDSCRIPT="1"
197+FEATURE_DIFF3_MERGE="1"
198+FEATURE_DIFF_BRIEF="1"
199+FEATURE_DIFF_CONTEXT="1"
200+FEATURE_DIFF_ED="1"
201+FEATURE_DIFF_SIDEBYSIDE="1"
202+FEATURE_DIFF_UNIFIED="1"
203+FEATURE_FIND_AMIN="1"
204+FEATURE_FIND_CMIN="1"
205+FEATURE_FIND_DELETE="1"
206+FEATURE_FIND_EMPTY="1"
207+FEATURE_FIND_INAME="1"
208+FEATURE_FIND_INUM="1"
209+FEATURE_FIND_IPATH="1"
210+FEATURE_FIND_MAXDEPTH="1"
211+FEATURE_FIND_MINDEPTH="1"
212+FEATURE_FIND_MMIN="1"
213+FEATURE_FIND_PRINT0="1"
214+FEATURE_FIND_QUIT="1"
215+FEATURE_FIND_REGEX="1"
216+FEATURE_FIND_SAMEFILE="1"
217+FEATURE_GREP_CONTEXT="1"
218+FEATURE_GREP_MAX_COUNT="1"
219+FEATURE_INPROC_EXEC="0"
220+FEATURE_INPROC_EXEC_OVERRIDE="0"
221+FEATURE_IP_ADDR_FLUSH="1"
222+FEATURE_IP_LINK_SET="1"
223+FEATURE_IP_ROUTE_ADD_DEL="1"
224+FEATURE_LS_COLOR="1"
225+FEATURE_MODPROBE_BLACKLIST="1"
226+FEATURE_MODPROBE_DIR_OVERRIDE="1"
227+FEATURE_MODPROBE_SHOW_DEPENDS="1"
228+FEATURE_MODPROBE_SYSLOG="1"
229+FEATURE_OD_ENDIAN="1"
230+FEATURE_PATCH_BACKUP="1"
231+FEATURE_PATCH_FUZZ="1"
232+FEATURE_PATCH_STRIP_CR="1"
233+FEATURE_READLINK_REALPATH="1"
234+FEATURE_SED_INPLACE="1"
235+FEATURE_SED_PRESERVE_NEWLINE="1"
236+FEATURE_SH_EASTER="0"
237+FEATURE_SH_HISTEDIT="1"
238+FEATURE_SH_LET="1"
239+FEATURE_SH_LOCAL="1"
240+FEATURE_SH_SETVAR="1"
241+FEATURE_SH_ULIMIT="1"
242+FEATURE_SH_WORDEXP="1"
243+FEATURE_SORT_BIG="1"
244+FEATURE_SORT_STABLE="1"
245+FEATURE_STAT_FILESYSTEM="1"
246+FEATURE_STAT_FORMAT="1"
247+FEATURE_TAR_CREATE="1"
248+FEATURE_TAR_EXCLUDE="1"
249+FEATURE_TAR_EXCLUDE_FROM="1"
250+FEATURE_TAR_FILES_FROM="1"
251+FEATURE_TAR_KEEP_OLD="1"
252+FEATURE_TAR_NOFOLLOW="1"
253+FEATURE_TAR_STRIP_COMPONENTS="1"
254+FEATURE_TAR_TO_STDOUT="1"
255+FEATURE_TAR_TTY_SAFE="1"
256+FEATURE_UMOUNT_OPTIONS="1"
257+FEATURE_USE_BEARSSL="0"
258+FEATURE_USE_LIBRESSL="0"
259+FEATURE_USE_OPENSSL="0"
260+FEATURE_USE_SSL="1"
261+CPPFLAGS_TLS=""
262+LDFLAGS_TLS=""
263+LDLIBS_TLS=""
R config.mk => scripts/mk/config.mk
+206, -199
  1@@ -1,21 +1,23 @@
  2-VERSION = 2026-06-17T10-19-UTC
  3-PREFIX    = /usr/local
  4-MANPREFIX = $(PREFIX)/share/man
  5-
  6-RANLIB  = ranlib
  7-AR      = ar
  8+VERSION = 2026-06-08T05-53-UTC-03
  9+PREFIX = /usr/local
 10+MANPREFIX = /usr/local/share/man
 11+RANLIB = ranlib
 12+AR = ar
 13 ARFLAGS = rc
 14 
 15 # build toggles
 16-BUILD_POSIX  = 1
 17-BUILD_LINUX  = 1
 18-BUILD_NET    = 1
 19-BUILD_XSI    = 1
 20+BUILD_POSIX = 1
 21+BUILD_XSI = 1
 22+BUILD_NET = 1
 23 BUILD_PSEUDO = 1
 24-BUILD_DEV    = 0
 25+BUILD_EXTRA = 1
 26+BUILD_LINUX = 1
 27+BUILD_DEV = 0
 28 
 29-# include all sub-targets
 30+# posix subtargets
 31+BUILD_POSIX_AWK = $(BUILD_POSIX)
 32 BUILD_POSIX_BASENAME = $(BUILD_POSIX)
 33+BUILD_POSIX_BC = $(BUILD_POSIX)
 34 BUILD_POSIX_CAL = $(BUILD_POSIX)
 35 BUILD_POSIX_CAT = $(BUILD_POSIX)
 36 BUILD_POSIX_CHGRP = $(BUILD_POSIX)
 37@@ -30,7 +32,6 @@ BUILD_POSIX_DATE = $(BUILD_POSIX)
 38 BUILD_POSIX_DD = $(BUILD_POSIX)
 39 BUILD_POSIX_DF = $(BUILD_POSIX)
 40 BUILD_POSIX_DIFF = $(BUILD_POSIX)
 41-BUILD_POSIX_PATCH = $(BUILD_POSIX)
 42 BUILD_POSIX_DIRNAME = $(BUILD_POSIX)
 43 BUILD_POSIX_DU = $(BUILD_POSIX)
 44 BUILD_POSIX_ECHO = $(BUILD_POSIX)
 45@@ -52,6 +53,7 @@ BUILD_POSIX_LN = $(BUILD_POSIX)
 46 BUILD_POSIX_LOGGER = $(BUILD_POSIX)
 47 BUILD_POSIX_LOGNAME = $(BUILD_POSIX)
 48 BUILD_POSIX_LS = $(BUILD_POSIX)
 49+BUILD_POSIX_MAKE = $(BUILD_POSIX)
 50 BUILD_POSIX_MESG = $(BUILD_POSIX)
 51 BUILD_POSIX_MKDIR = $(BUILD_POSIX)
 52 BUILD_POSIX_MKFIFO = $(BUILD_POSIX)
 53@@ -61,7 +63,9 @@ BUILD_POSIX_NL = $(BUILD_POSIX)
 54 BUILD_POSIX_NOHUP = $(BUILD_POSIX)
 55 BUILD_POSIX_OD = $(BUILD_POSIX)
 56 BUILD_POSIX_PASTE = $(BUILD_POSIX)
 57+BUILD_POSIX_PATCH = $(BUILD_POSIX)
 58 BUILD_POSIX_PATHCHK = $(BUILD_POSIX)
 59+BUILD_POSIX_PAX = $(BUILD_POSIX)
 60 BUILD_POSIX_PRINTF = $(BUILD_POSIX)
 61 BUILD_POSIX_PS = $(BUILD_POSIX)
 62 BUILD_POSIX_PWD = $(BUILD_POSIX)
 63@@ -70,6 +74,7 @@ BUILD_POSIX_RENICE = $(BUILD_POSIX)
 64 BUILD_POSIX_RM = $(BUILD_POSIX)
 65 BUILD_POSIX_RMDIR = $(BUILD_POSIX)
 66 BUILD_POSIX_SED = $(BUILD_POSIX)
 67+BUILD_POSIX_SH = $(BUILD_POSIX)
 68 BUILD_POSIX_SLEEP = $(BUILD_POSIX)
 69 BUILD_POSIX_SORT = $(BUILD_POSIX)
 70 BUILD_POSIX_SPLIT = $(BUILD_POSIX)
 71@@ -91,59 +96,34 @@ BUILD_POSIX_UUENCODE = $(BUILD_POSIX)
 72 BUILD_POSIX_WC = $(BUILD_POSIX)
 73 BUILD_POSIX_WHO = $(BUILD_POSIX)
 74 BUILD_POSIX_XARGS = $(BUILD_POSIX)
 75-BUILD_POSIX_AWK = $(BUILD_POSIX)
 76-BUILD_POSIX_SH = $(BUILD_POSIX)
 77-BUILD_POSIX_PAX = $(BUILD_POSIX)
 78 
 79-# linux tools
 80-BUILD_LINUX_BLKDISCARD = $(BUILD_LINUX)
 81-BUILD_LINUX_CHVT = $(BUILD_LINUX)
 82-BUILD_LINUX_CTRLALTDEL = $(BUILD_LINUX)
 83-BUILD_LINUX_EJECT = $(BUILD_LINUX)
 84-BUILD_LINUX_FREERAMDISK = $(BUILD_LINUX)
 85-BUILD_LINUX_FSFREEZE = $(BUILD_LINUX)
 86-BUILD_LINUX_HWCLOCK = $(BUILD_LINUX)
 87-BUILD_LINUX_INSMOD = $(BUILD_LINUX)
 88-BUILD_LINUX_LSMOD = $(BUILD_LINUX)
 89-BUILD_LINUX_MODPROBE = $(BUILD_LINUX)
 90-BUILD_LINUX_DEPMOD = $(BUILD_LINUX)
 91-BUILD_LINUX_MKSWAP = $(BUILD_LINUX)
 92-BUILD_LINUX_MOUNT = $(BUILD_LINUX)
 93-BUILD_LINUX_MOUNTPOINT = $(BUILD_LINUX)
 94-BUILD_LINUX_PIVOT_ROOT = $(BUILD_LINUX)
 95-BUILD_LINUX_READAHEAD = $(BUILD_LINUX)
 96-BUILD_LINUX_RMMOD = $(BUILD_LINUX)
 97-BUILD_LINUX_SWAPLABEL = $(BUILD_LINUX)
 98-BUILD_LINUX_SWAPOFF = $(BUILD_LINUX)
 99-BUILD_LINUX_SWAPON = $(BUILD_LINUX)
100-BUILD_LINUX_SWITCH_ROOT = $(BUILD_LINUX)
101-BUILD_LINUX_TUNCTL = $(BUILD_LINUX)
102-BUILD_LINUX_UMOUNT = $(BUILD_LINUX)
103-BUILD_LINUX_UNSHARE = $(BUILD_LINUX)
104-BUILD_LINUX_VTALLOW = $(BUILD_LINUX)
105+# xsi subtargets
106+BUILD_XSI_MKNOD = $(BUILD_XSI)
107+BUILD_XSI_PASSWD = $(BUILD_XSI)
108+BUILD_XSI_SU = $(BUILD_XSI)
109 
110-# net tools
111-BUILD_NET_NETCAT = $(BUILD_NET)
112-BUILD_NET_TFTP = $(BUILD_NET)
113-BUILD_NET_WGET = $(BUILD_NET)
114-BUILD_NET_PING = $(BUILD_NET)
115-BUILD_NET_SDHCP = $(BUILD_NET)
116-BUILD_NET_IFCONFIG = $(BUILD_NET)
117+# net subtargets
118 BUILD_NET_HOST = $(BUILD_NET)
119 BUILD_NET_HTTPD = $(BUILD_NET)
120+BUILD_NET_IFCONFIG = $(BUILD_NET)
121 BUILD_NET_IP = $(BUILD_NET)
122+BUILD_NET_NETCAT = $(BUILD_NET)
123+BUILD_NET_PING = $(BUILD_NET)
124+BUILD_NET_SDHCP = $(BUILD_NET)
125+BUILD_NET_TFTP = $(BUILD_NET)
126+BUILD_NET_WGET = $(BUILD_NET)
127 
128-# xsi tools
129-BUILD_XSI_MKNOD = $(BUILD_XSI)
130-BUILD_XSI_PASSWD = $(BUILD_XSI)
131-BUILD_XSI_SU = $(BUILD_XSI)
132-
133-# pseudo tools
134+# pseudo subtargets
135+BUILD_PSEUDO_BASE64 = $(BUILD_PSEUDO)
136 BUILD_PSEUDO_CHROOT = $(BUILD_PSEUDO)
137 BUILD_PSEUDO_CLEAR = $(BUILD_PSEUDO)
138 BUILD_PSEUDO_COLS = $(BUILD_PSEUDO)
139 BUILD_PSEUDO_CRON = $(BUILD_PSEUDO)
140+BUILD_PSEUDO_DIFF3 = $(BUILD_PSEUDO)
141+BUILD_PSEUDO_DMESG = $(BUILD_PSEUDO)
142+BUILD_PSEUDO_FALLOCATE = $(BUILD_PSEUDO)
143 BUILD_PSEUDO_FLOCK = $(BUILD_PSEUDO)
144+BUILD_PSEUDO_FREE = $(BUILD_PSEUDO)
145 BUILD_PSEUDO_GETTY = $(BUILD_PSEUDO)
146 BUILD_PSEUDO_HALT = $(BUILD_PSEUDO)
147 BUILD_PSEUDO_HOSTNAME = $(BUILD_PSEUDO)
148@@ -152,10 +132,13 @@ BUILD_PSEUDO_LAST = $(BUILD_PSEUDO)
149 BUILD_PSEUDO_LASTLOG = $(BUILD_PSEUDO)
150 BUILD_PSEUDO_LOGIN = $(BUILD_PSEUDO)
151 BUILD_PSEUDO_MD5SUM = $(BUILD_PSEUDO)
152+BUILD_PSEUDO_MKPASSWD = $(BUILD_PSEUDO)
153 BUILD_PSEUDO_MKTEMP = $(BUILD_PSEUDO)
154 BUILD_PSEUDO_NOLOGIN = $(BUILD_PSEUDO)
155 BUILD_PSEUDO_PAGESIZE = $(BUILD_PSEUDO)
156+BUILD_PSEUDO_PIDOF = $(BUILD_PSEUDO)
157 BUILD_PSEUDO_PRINTENV = $(BUILD_PSEUDO)
158+BUILD_PSEUDO_PWDX = $(BUILD_PSEUDO)
159 BUILD_PSEUDO_RESPAWN = $(BUILD_PSEUDO)
160 BUILD_PSEUDO_REV = $(BUILD_PSEUDO)
161 BUILD_PSEUDO_SEQ = $(BUILD_PSEUDO)
162@@ -164,107 +147,138 @@ BUILD_PSEUDO_SHA1SUM = $(BUILD_PSEUDO)
163 BUILD_PSEUDO_SHA224SUM = $(BUILD_PSEUDO)
164 BUILD_PSEUDO_SHA256SUM = $(BUILD_PSEUDO)
165 BUILD_PSEUDO_SHA384SUM = $(BUILD_PSEUDO)
166-BUILD_PSEUDO_SHA512SUM = $(BUILD_PSEUDO)
167 BUILD_PSEUDO_SHA512_224SUM = $(BUILD_PSEUDO)
168 BUILD_PSEUDO_SHA512_256SUM = $(BUILD_PSEUDO)
169+BUILD_PSEUDO_SHA512SUM = $(BUILD_PSEUDO)
170 BUILD_PSEUDO_SPONGE = $(BUILD_PSEUDO)
171 BUILD_PSEUDO_STAT = $(BUILD_PSEUDO)
172 BUILD_PSEUDO_TAR = $(BUILD_PSEUDO)
173 BUILD_PSEUDO_TRUNCATE = $(BUILD_PSEUDO)
174+BUILD_PSEUDO_UPTIME = $(BUILD_PSEUDO)
175 BUILD_PSEUDO_WATCH = $(BUILD_PSEUDO)
176 BUILD_PSEUDO_WHICH = $(BUILD_PSEUDO)
177 BUILD_PSEUDO_WHOAMI = $(BUILD_PSEUDO)
178 BUILD_PSEUDO_XINSTALL = $(BUILD_PSEUDO)
179 BUILD_PSEUDO_YES = $(BUILD_PSEUDO)
180-BUILD_PSEUDO_BASE64 = $(BUILD_PSEUDO)
181-BUILD_PSEUDO_B3SUM = $(BUILD_PSEUDO)
182-BUILD_PSEUDO_BLKID = $(BUILD_PSEUDO)
183-BUILD_PSEUDO_LSBLK = $(BUILD_PSEUDO)
184-BUILD_PSEUDO_FDISK = $(BUILD_PSEUDO)
185-BUILD_PSEUDO_DIFF3 = $(BUILD_PSEUDO)
186-BUILD_PSEUDO_SYNC = $(BUILD_PSEUDO)
187-BUILD_PSEUDO_DMESG = $(BUILD_PSEUDO)
188-BUILD_PSEUDO_FALLOCATE = $(BUILD_PSEUDO)
189-BUILD_PSEUDO_FREE = $(BUILD_PSEUDO)
190-BUILD_PSEUDO_PIDOF = $(BUILD_PSEUDO)
191-BUILD_PSEUDO_PWDX = $(BUILD_PSEUDO)
192-BUILD_PSEUDO_UPTIME = $(BUILD_PSEUDO)
193 
194-# dev tools
195+# extra subtargets
196+BUILD_EXTRA_B3SUM = $(BUILD_EXTRA)
197+BUILD_EXTRA_BLKID = $(BUILD_EXTRA)
198+BUILD_EXTRA_FDISK = $(BUILD_EXTRA)
199+BUILD_EXTRA_LSBLK = $(BUILD_EXTRA)
200+BUILD_EXTRA_SYNC = $(BUILD_EXTRA)
201+BUILD_EXTRA_YAP = $(BUILD_EXTRA)
202+
203+# linux subtargets
204+BUILD_LINUX_BLKDISCARD = $(BUILD_LINUX)
205+BUILD_LINUX_CHVT = $(BUILD_LINUX)
206+BUILD_LINUX_CTRLALTDEL = $(BUILD_LINUX)
207+BUILD_LINUX_DEPMOD = $(BUILD_LINUX)
208+BUILD_LINUX_EJECT = $(BUILD_LINUX)
209+BUILD_LINUX_FREERAMDISK = $(BUILD_LINUX)
210+BUILD_LINUX_FSFREEZE = $(BUILD_LINUX)
211+BUILD_LINUX_HWCLOCK = $(BUILD_LINUX)
212+BUILD_LINUX_INSMOD = $(BUILD_LINUX)
213+BUILD_LINUX_LSMOD = $(BUILD_LINUX)
214+BUILD_LINUX_LSUSB = $(BUILD_LINUX)
215+BUILD_LINUX_MKSWAP = $(BUILD_LINUX)
216+BUILD_LINUX_MODPROBE = $(BUILD_LINUX)
217+BUILD_LINUX_MOUNT = $(BUILD_LINUX)
218+BUILD_LINUX_MOUNTPOINT = $(BUILD_LINUX)
219+BUILD_LINUX_PIVOT_ROOT = $(BUILD_LINUX)
220+BUILD_LINUX_READAHEAD = $(BUILD_LINUX)
221+BUILD_LINUX_RMMOD = $(BUILD_LINUX)
222+BUILD_LINUX_SWAPLABEL = $(BUILD_LINUX)
223+BUILD_LINUX_SWAPOFF = $(BUILD_LINUX)
224+BUILD_LINUX_SWAPON = $(BUILD_LINUX)
225+BUILD_LINUX_SWITCH_ROOT = $(BUILD_LINUX)
226+BUILD_LINUX_SYSCTL = $(BUILD_LINUX)
227+BUILD_LINUX_TUNCTL = $(BUILD_LINUX)
228+BUILD_LINUX_UMOUNT = $(BUILD_LINUX)
229+BUILD_LINUX_UNSHARE = $(BUILD_LINUX)
230+BUILD_LINUX_VTALLOW = $(BUILD_LINUX)
231+
232+# dev subtargets
233 BUILD_DEV_AR = $(BUILD_DEV)
234-BUILD_DEV_LD = $(BUILD_DEV)
235 BUILD_DEV_AS = $(BUILD_DEV)
236 BUILD_DEV_CC = $(BUILD_DEV)
237+BUILD_DEV_LD = $(BUILD_DEV)
238+BUILD_DEV_SCRATCHPAD = $(BUILD_DEV)
239+BUILD_DEV_XCUTIL = $(BUILD_DEV)
240 
241-# make tool
242-BUILD_POSIX_MAKE = $(BUILD_POSIX)
243-
244-FEATURE_FIND_DELETE     = 1
245-FEATURE_FIND_QUIT       = 1
246-FEATURE_FIND_EMPTY      = 1
247-FEATURE_FIND_INUM       = 1
248-FEATURE_FIND_SAMEFILE   = 1
249-FEATURE_FIND_MAXDEPTH   = 1
250-FEATURE_FIND_MINDEPTH   = 1
251-FEATURE_FIND_MMIN       = 1
252-FEATURE_FIND_AMIN       = 1
253-FEATURE_FIND_CMIN       = 1
254-FEATURE_FIND_INAME      = 1
255-FEATURE_FIND_IPATH      = 1
256-FEATURE_FIND_REGEX      = 1
257-FEATURE_FIND_PRINT0     = 1
258-FEATURE_SED_INPLACE     = 1
259-FEATURE_GREP_CONTEXT    = 1
260-FEATURE_GREP_MAX_COUNT  = 1
261-FEATURE_TAR_CREATE      = 1
262-FEATURE_TAR_EXCLUDE     = 1
263-FEATURE_STAT_FILESYSTEM = 1
264-FEATURE_STAT_FORMAT     = 1
265-FEATURE_SORT_BIG        = 1
266-FEATURE_SORT_STABLE     = 1
267-FEATURE_OD_ENDIAN       = 1
268-FEATURE_SH_EASTER       = 1
269-FEATURE_SH_HISTEDIT     = 1
270-FEATURE_SH_LOCAL        = 1
271-FEATURE_SH_LET          = 1
272-FEATURE_SH_ULIMIT       = 1
273-FEATURE_SH_SETVAR       = 1
274-FEATURE_SH_WORDEXP      = 1
275-FEATURE_CAL_EXT         = 1
276-FEATURE_SED_PRESERVE_NEWLINE = 1
277-FEATURE_LS_COLOR             = 1
278-FEATURE_DIFF3_MERGE          = 1
279-FEATURE_DIFF3_EDSCRIPT       = 1
280-FEATURE_DIFF_CONTEXT         = 1
281-FEATURE_DIFF_UNIFIED         = 1
282-FEATURE_DIFF_ED              = 1
283-FEATURE_DIFF_BRIEF           = 1
284-FEATURE_DIFF_SIDEBYSIDE      = 1
285-FEATURE_PATCH_BACKUP         = 1
286-FEATURE_PATCH_FUZZ           = 1
287-FEATURE_PATCH_STRIP_CR       = 1
288-FEATURE_INPROC_EXEC          = 0
289-FEATURE_MODPROBE_SHOW_DEPENDS = 1
290-FEATURE_MODPROBE_BLACKLIST   = 1
291-FEATURE_MODPROBE_SYSLOG      = 1
292-FEATURE_MODPROBE_DIR_OVERRIDE = 1
293-FEATURE_DEPMOD_ALIAS   = 1
294+# feature flags
295+FEATURE_CAL_EXT = 1
296+FEATURE_DEPMOD_ALIAS = 1
297 FEATURE_DEPMOD_SYMBOLS = 1
298-FEATURE_USE_LIBRESSL = 0
299-FEATURE_USE_BEARSSL = 0
300-FEATURE_USE_OPENSSL = 0
301-FEATURE_TAR_TTY_SAFE = 1
302-FEATURE_TAR_NOFOLLOW = 1
303+FEATURE_DIFF3_EDSCRIPT = 1
304+FEATURE_DIFF3_MERGE = 1
305+FEATURE_DIFF_BRIEF = 1
306+FEATURE_DIFF_CONTEXT = 1
307+FEATURE_DIFF_ED = 1
308+FEATURE_DIFF_SIDEBYSIDE = 1
309+FEATURE_DIFF_UNIFIED = 1
310+FEATURE_FIND_AMIN = 1
311+FEATURE_FIND_CMIN = 1
312+FEATURE_FIND_DELETE = 1
313+FEATURE_FIND_EMPTY = 1
314+FEATURE_FIND_INAME = 1
315+FEATURE_FIND_INUM = 1
316+FEATURE_FIND_IPATH = 1
317+FEATURE_FIND_MAXDEPTH = 1
318+FEATURE_FIND_MINDEPTH = 1
319+FEATURE_FIND_MMIN = 1
320+FEATURE_FIND_PRINT0 = 1
321+FEATURE_FIND_QUIT = 1
322+FEATURE_FIND_REGEX = 1
323+FEATURE_FIND_SAMEFILE = 1
324+FEATURE_GREP_CONTEXT = 1
325+FEATURE_GREP_MAX_COUNT = 1
326+FEATURE_INPROC_EXEC = 0
327+FEATURE_INPROC_EXEC_OVERRIDE = 0
328+FEATURE_IP_ADDR_FLUSH = 1
329+FEATURE_IP_LINK_SET = 1
330+FEATURE_IP_ROUTE_ADD_DEL = 1
331+FEATURE_LS_COLOR = 1
332+FEATURE_MODPROBE_BLACKLIST = 1
333+FEATURE_MODPROBE_DIR_OVERRIDE = 1
334+FEATURE_MODPROBE_SHOW_DEPENDS = 1
335+FEATURE_MODPROBE_SYSLOG = 1
336+FEATURE_OD_ENDIAN = 1
337+FEATURE_PATCH_BACKUP = 1
338+FEATURE_PATCH_FUZZ = 1
339+FEATURE_PATCH_STRIP_CR = 1
340 FEATURE_READLINK_REALPATH = 1
341-FEATURE_UMOUNT_OPTIONS = 1
342-FEATURE_TAR_TO_STDOUT = 1
343+FEATURE_SED_INPLACE = 1
344+FEATURE_SED_PRESERVE_NEWLINE = 1
345+FEATURE_SH_EASTER = 0
346+FEATURE_SH_HISTEDIT = 1
347+FEATURE_SH_LET = 1
348+FEATURE_SH_LOCAL = 1
349+FEATURE_SH_SETVAR = 1
350+FEATURE_SH_ULIMIT = 1
351+FEATURE_SH_WORDEXP = 1
352+FEATURE_SORT_BIG = 1
353+FEATURE_SORT_STABLE = 1
354+FEATURE_STAT_FILESYSTEM = 1
355+FEATURE_STAT_FORMAT = 1
356+FEATURE_TAR_CREATE = 1
357+FEATURE_TAR_EXCLUDE = 1
358+FEATURE_TAR_EXCLUDE_FROM = 1
359+FEATURE_TAR_FILES_FROM = 1
360 FEATURE_TAR_KEEP_OLD = 1
361+FEATURE_TAR_NOFOLLOW = 1
362 FEATURE_TAR_STRIP_COMPONENTS = 1
363-FEATURE_TAR_FILES_FROM = 1
364-FEATURE_TAR_EXCLUDE_FROM = 1
365-FEATURE_IP_ROUTE_ADD_DEL = 1
366-FEATURE_IP_LINK_SET = 1
367-FEATURE_IP_ADDR_FLUSH = 1
368+FEATURE_TAR_TO_STDOUT = 1
369+FEATURE_TAR_TTY_SAFE = 1
370+FEATURE_UMOUNT_OPTIONS = 1
371+FEATURE_USE_BEARSSL = 0
372+FEATURE_USE_LIBRESSL = 0
373+FEATURE_USE_OPENSSL = 0
374+FEATURE_USE_SSL = 1
375+
376+CPPFLAGS_TLS = 
377+LDFLAGS_TLS = 
378+LDLIBS_TLS = 
379 
380 CPPFLAGS =\
381         -Ishared\
382@@ -275,83 +289,76 @@ CPPFLAGS =\
383         -D_BSD_SOURCE\
384         -D_XOPEN_SOURCE=700\
385         -D_FILE_OFFSET_BITS=64\
386+        -DFEATURE_CAL_EXT=$(FEATURE_CAL_EXT)\
387+        -DFEATURE_DEPMOD_ALIAS=$(FEATURE_DEPMOD_ALIAS)\
388+        -DFEATURE_DEPMOD_SYMBOLS=$(FEATURE_DEPMOD_SYMBOLS)\
389+        -DFEATURE_DIFF3_EDSCRIPT=$(FEATURE_DIFF3_EDSCRIPT)\
390+        -DFEATURE_DIFF3_MERGE=$(FEATURE_DIFF3_MERGE)\
391+        -DFEATURE_DIFF_BRIEF=$(FEATURE_DIFF_BRIEF)\
392+        -DFEATURE_DIFF_CONTEXT=$(FEATURE_DIFF_CONTEXT)\
393+        -DFEATURE_DIFF_ED=$(FEATURE_DIFF_ED)\
394+        -DFEATURE_DIFF_SIDEBYSIDE=$(FEATURE_DIFF_SIDEBYSIDE)\
395+        -DFEATURE_DIFF_UNIFIED=$(FEATURE_DIFF_UNIFIED)\
396+        -DFEATURE_FIND_AMIN=$(FEATURE_FIND_AMIN)\
397+        -DFEATURE_FIND_CMIN=$(FEATURE_FIND_CMIN)\
398         -DFEATURE_FIND_DELETE=$(FEATURE_FIND_DELETE)\
399-        -DFEATURE_FIND_QUIT=$(FEATURE_FIND_QUIT)\
400         -DFEATURE_FIND_EMPTY=$(FEATURE_FIND_EMPTY)\
401+        -DFEATURE_FIND_INAME=$(FEATURE_FIND_INAME)\
402         -DFEATURE_FIND_INUM=$(FEATURE_FIND_INUM)\
403-        -DFEATURE_FIND_SAMEFILE=$(FEATURE_FIND_SAMEFILE)\
404+        -DFEATURE_FIND_IPATH=$(FEATURE_FIND_IPATH)\
405         -DFEATURE_FIND_MAXDEPTH=$(FEATURE_FIND_MAXDEPTH)\
406         -DFEATURE_FIND_MINDEPTH=$(FEATURE_FIND_MINDEPTH)\
407         -DFEATURE_FIND_MMIN=$(FEATURE_FIND_MMIN)\
408-        -DFEATURE_FIND_AMIN=$(FEATURE_FIND_AMIN)\
409-        -DFEATURE_FIND_CMIN=$(FEATURE_FIND_CMIN)\
410-        -DFEATURE_FIND_INAME=$(FEATURE_FIND_INAME)\
411-        -DFEATURE_FIND_IPATH=$(FEATURE_FIND_IPATH)\
412-        -DFEATURE_FIND_REGEX=$(FEATURE_FIND_REGEX)\
413         -DFEATURE_FIND_PRINT0=$(FEATURE_FIND_PRINT0)\
414-        -DFEATURE_SED_INPLACE=$(FEATURE_SED_INPLACE)\
415+        -DFEATURE_FIND_QUIT=$(FEATURE_FIND_QUIT)\
416+        -DFEATURE_FIND_REGEX=$(FEATURE_FIND_REGEX)\
417+        -DFEATURE_FIND_SAMEFILE=$(FEATURE_FIND_SAMEFILE)\
418         -DFEATURE_GREP_CONTEXT=$(FEATURE_GREP_CONTEXT)\
419         -DFEATURE_GREP_MAX_COUNT=$(FEATURE_GREP_MAX_COUNT)\
420-        -DFEATURE_TAR_CREATE=$(FEATURE_TAR_CREATE)\
421-        -DFEATURE_TAR_EXCLUDE=$(FEATURE_TAR_EXCLUDE)\
422-        -DFEATURE_STAT_FILESYSTEM=$(FEATURE_STAT_FILESYSTEM)\
423-        -DFEATURE_STAT_FORMAT=$(FEATURE_STAT_FORMAT)\
424-        -DFEATURE_SORT_BIG=$(FEATURE_SORT_BIG)\
425-        -DFEATURE_SORT_STABLE=$(FEATURE_SORT_STABLE)\
426-        -DFEATURE_OD_ENDIAN=$(FEATURE_OD_ENDIAN)\
427-        -DFEATURE_SH_HISTEDIT=$(FEATURE_SH_HISTEDIT)\
428-        -DFEATURE_SH_LOCAL=$(FEATURE_SH_LOCAL)\
429-        -DFEATURE_SH_LET=$(FEATURE_SH_LET)\
430-        -DFEATURE_SH_ULIMIT=$(FEATURE_SH_ULIMIT)\
431-        -DFEATURE_SH_SETVAR=$(FEATURE_SH_SETVAR)\
432-        -DFEATURE_SH_WORDEXP=$(FEATURE_SH_WORDEXP)\
433-        -DFEATURE_CAL_EXT=$(FEATURE_CAL_EXT)\
434-        -DFEATURE_SED_PRESERVE_NEWLINE=$(FEATURE_SED_PRESERVE_NEWLINE)\
435+        -DFEATURE_INPROC_EXEC=$(FEATURE_INPROC_EXEC)\
436+        -DFEATURE_INPROC_EXEC_OVERRIDE=$(FEATURE_INPROC_EXEC_OVERRIDE)\
437+        -DFEATURE_IP_ADDR_FLUSH=$(FEATURE_IP_ADDR_FLUSH)\
438+        -DFEATURE_IP_LINK_SET=$(FEATURE_IP_LINK_SET)\
439+        -DFEATURE_IP_ROUTE_ADD_DEL=$(FEATURE_IP_ROUTE_ADD_DEL)\
440         -DFEATURE_LS_COLOR=$(FEATURE_LS_COLOR)\
441-        -DFEATURE_DIFF3_MERGE=$(FEATURE_DIFF3_MERGE)\
442-        -DFEATURE_DIFF3_EDSCRIPT=$(FEATURE_DIFF3_EDSCRIPT)\
443-        -DFEATURE_DIFF_CONTEXT=$(FEATURE_DIFF_CONTEXT)\
444-        -DFEATURE_DIFF_UNIFIED=$(FEATURE_DIFF_UNIFIED)\
445-        -DFEATURE_DIFF_ED=$(FEATURE_DIFF_ED)\
446-        -DFEATURE_DIFF_BRIEF=$(FEATURE_DIFF_BRIEF)\
447-        -DFEATURE_DIFF_SIDEBYSIDE=$(FEATURE_DIFF_SIDEBYSIDE)\
448+        -DFEATURE_MODPROBE_BLACKLIST=$(FEATURE_MODPROBE_BLACKLIST)\
449+        -DFEATURE_MODPROBE_DIR_OVERRIDE=$(FEATURE_MODPROBE_DIR_OVERRIDE)\
450+        -DFEATURE_MODPROBE_SHOW_DEPENDS=$(FEATURE_MODPROBE_SHOW_DEPENDS)\
451+        -DFEATURE_MODPROBE_SYSLOG=$(FEATURE_MODPROBE_SYSLOG)\
452+        -DFEATURE_OD_ENDIAN=$(FEATURE_OD_ENDIAN)\
453         -DFEATURE_PATCH_BACKUP=$(FEATURE_PATCH_BACKUP)\
454         -DFEATURE_PATCH_FUZZ=$(FEATURE_PATCH_FUZZ)\
455         -DFEATURE_PATCH_STRIP_CR=$(FEATURE_PATCH_STRIP_CR)\
456-        -DFEATURE_INPROC_EXEC=$(FEATURE_INPROC_EXEC)\
457-        -DFEATURE_MODPROBE_SHOW_DEPENDS=$(FEATURE_MODPROBE_SHOW_DEPENDS)\
458-        -DFEATURE_MODPROBE_BLACKLIST=$(FEATURE_MODPROBE_BLACKLIST)\
459-        -DFEATURE_MODPROBE_SYSLOG=$(FEATURE_MODPROBE_SYSLOG)\
460-        -DFEATURE_MODPROBE_DIR_OVERRIDE=$(FEATURE_MODPROBE_DIR_OVERRIDE)\
461-        -DFEATURE_DEPMOD_ALIAS=$(FEATURE_DEPMOD_ALIAS)\
462-        -DFEATURE_DEPMOD_SYMBOLS=$(FEATURE_DEPMOD_SYMBOLS)\
463-        -DFEATURE_USE_LIBRESSL=$(FEATURE_USE_LIBRESSL)\
464-        -DFEATURE_USE_BEARSSL=$(FEATURE_USE_BEARSSL)\
465-        -DFEATURE_USE_OPENSSL=$(FEATURE_USE_OPENSSL)\
466-        -DFEATURE_TAR_TTY_SAFE=$(FEATURE_TAR_TTY_SAFE)\
467-        -DFEATURE_TAR_NOFOLLOW=$(FEATURE_TAR_NOFOLLOW)\
468         -DFEATURE_READLINK_REALPATH=$(FEATURE_READLINK_REALPATH)\
469-        -DFEATURE_UMOUNT_OPTIONS=$(FEATURE_UMOUNT_OPTIONS)\
470-        -DFEATURE_TAR_TO_STDOUT=$(FEATURE_TAR_TO_STDOUT)\
471+        -DFEATURE_SED_INPLACE=$(FEATURE_SED_INPLACE)\
472+        -DFEATURE_SED_PRESERVE_NEWLINE=$(FEATURE_SED_PRESERVE_NEWLINE)\
473+        -DFEATURE_SH_EASTER=$(FEATURE_SH_EASTER)\
474+        -DFEATURE_SH_HISTEDIT=$(FEATURE_SH_HISTEDIT)\
475+        -DFEATURE_SH_LET=$(FEATURE_SH_LET)\
476+        -DFEATURE_SH_LOCAL=$(FEATURE_SH_LOCAL)\
477+        -DFEATURE_SH_SETVAR=$(FEATURE_SH_SETVAR)\
478+        -DFEATURE_SH_ULIMIT=$(FEATURE_SH_ULIMIT)\
479+        -DFEATURE_SH_WORDEXP=$(FEATURE_SH_WORDEXP)\
480+        -DFEATURE_SORT_BIG=$(FEATURE_SORT_BIG)\
481+        -DFEATURE_SORT_STABLE=$(FEATURE_SORT_STABLE)\
482+        -DFEATURE_STAT_FILESYSTEM=$(FEATURE_STAT_FILESYSTEM)\
483+        -DFEATURE_STAT_FORMAT=$(FEATURE_STAT_FORMAT)\
484+        -DFEATURE_TAR_CREATE=$(FEATURE_TAR_CREATE)\
485+        -DFEATURE_TAR_EXCLUDE=$(FEATURE_TAR_EXCLUDE)\
486+        -DFEATURE_TAR_EXCLUDE_FROM=$(FEATURE_TAR_EXCLUDE_FROM)\
487+        -DFEATURE_TAR_FILES_FROM=$(FEATURE_TAR_FILES_FROM)\
488         -DFEATURE_TAR_KEEP_OLD=$(FEATURE_TAR_KEEP_OLD)\
489+        -DFEATURE_TAR_NOFOLLOW=$(FEATURE_TAR_NOFOLLOW)\
490         -DFEATURE_TAR_STRIP_COMPONENTS=$(FEATURE_TAR_STRIP_COMPONENTS)\
491-        -DFEATURE_TAR_FILES_FROM=$(FEATURE_TAR_FILES_FROM)\
492-        -DFEATURE_TAR_EXCLUDE_FROM=$(FEATURE_TAR_EXCLUDE_FROM)\
493-        -DFEATURE_IP_ROUTE_ADD_DEL=$(FEATURE_IP_ROUTE_ADD_DEL)\
494-        -DFEATURE_IP_LINK_SET=$(FEATURE_IP_LINK_SET)\
495-        -DFEATURE_IP_ADDR_FLUSH=$(FEATURE_IP_ADDR_FLUSH) $(CPPFLAGS_TLS)
496+        -DFEATURE_TAR_TO_STDOUT=$(FEATURE_TAR_TO_STDOUT)\
497+        -DFEATURE_TAR_TTY_SAFE=$(FEATURE_TAR_TTY_SAFE)\
498+        -DFEATURE_UMOUNT_OPTIONS=$(FEATURE_UMOUNT_OPTIONS)\
499+        -DFEATURE_USE_BEARSSL=$(FEATURE_USE_BEARSSL)\
500+        -DFEATURE_USE_LIBRESSL=$(FEATURE_USE_LIBRESSL)\
501+        -DFEATURE_USE_OPENSSL=$(FEATURE_USE_OPENSSL)\
502+        $(CPPFLAGS_TLS)
503 
504-CC       = cc
505-CFLAGS   =
506-LDFLAGS  =
507-LDLIBS_HISTEDIT_0 =
508-LDLIBS_HISTEDIT_1 =
509-LDLIBS_TLS_LIBRESSL_1 = -ltls
510-LDLIBS_TLS_BEARSSL_1  = externalRepos/BearSSL/build/libbearssl.a
511-LDLIBS_TLS_OPENSSL_1  = -lssl -lcrypto
512-LDLIBS_TLS = $(LDLIBS_TLS_LIBRESSL_$(FEATURE_USE_LIBRESSL)) $(LDLIBS_TLS_BEARSSL_$(FEATURE_USE_BEARSSL)) $(LDLIBS_TLS_OPENSSL_$(FEATURE_USE_OPENSSL))
513-CPPFLAGS_TLS_BEARSSL_1 = -IexternalRepos/BearSSL/inc
514-LDFLAGS_TLS_BEARSSL_1  = -LexternalRepos/BearSSL/build
515-CPPFLAGS_TLS = $(CPPFLAGS_TLS_BEARSSL_$(FEATURE_USE_BEARSSL))
516-LDFLAGS_TLS  = $(LDFLAGS_TLS_BEARSSL_$(FEATURE_USE_BEARSSL))
517-LDLIBS   = -lcrypt -lresolv $(LDLIBS_HISTEDIT_$(FEATURE_SH_HISTEDIT))
518+CC = cc
519+CFLAGS = -std=c99 -Wall -Wextra -pedantic
520+LDFLAGS =  $(LDFLAGS_TLS)
521+LDLIBS = -lcrypt -lresolv $(LDLIBS_TLS)
+90, -115
  1@@ -2,21 +2,51 @@
  2 # mkbox - build aruu-box, the aruu multi-call binary
  3 #
  4 # expects CC CPPFLAGS CFLAGS LDFLAGS LDLIBS OBJCOPY YACC from the environment
  5-# defaults match config.mk but can be overridden
  6+# defaults match config.kv but can be overridden
  7 #
  8 # run from the source root (the Makefile does this automatically)
  9 
 10 set -e
 11 
 12+ROOT=$(CDPATH= cd "$(dirname "$0")/.." && pwd)
 13+
 14+# load key-value config if it exists
 15+if [ -f "${ROOT}/scripts/mk/config.kv" ]; then
 16+        . "${ROOT}/scripts/mk/config.kv"
 17+fi
 18+
 19 : "${CC:=cc}"
 20-: "${CPPFLAGS:=-Ishared -D_DEFAULT_SOURCE -D_GNU_SOURCE -D_NETBSD_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_FILE_OFFSET_BITS=64 -DFEATURE_INPROC_EXEC=1}"
 21 : "${CFLAGS:=-std=c99 -Wall -Wextra -pedantic}"
 22 : "${LDFLAGS:=}"
 23 : "${LDLIBS:=-lcrypt -lresolv}"
 24 : "${OBJCOPY:=objcopy}"
 25 : "${YACC:=yacc}"
 26 
 27-ROOT=$(CDPATH= cd "$(dirname "$0")/.." && pwd)
 28+# build feature flag string from loaded config.kv variables
 29+_feature_flags=""
 30+for _f in $(set | grep '^FEATURE_[A-Za-z0-9_]*=' | cut -d= -f1 | sort); do
 31+        eval "_v=\$$_f"
 32+        _feature_flags="$_feature_flags -D${_f}=${_v}"
 33+done
 34+unset _f _v
 35+
 36+CPPFLAGS="-Ishared -DPREFIX=\\\"${PREFIX:-/usr/local}\\\" -D_DEFAULT_SOURCE -D_GNU_SOURCE -D_NETBSD_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_FILE_OFFSET_BITS=64${_feature_flags} ${CPPFLAGS_TLS:-}"
 37+
 38+# -lm must be included if diff or awk is built
 39+if [ "${BUILD_POSIX_DIFF:-0}" = "1" ] || [ "${BUILD_POSIX_AWK:-0}" = "1" ]; then
 40+        case "$LDLIBS" in
 41+                *-lm*) ;;
 42+                *) LDLIBS="${LDLIBS} -lm" ;;
 43+        esac
 44+fi
 45+# -ltinfo must be included if yap is built
 46+if [ "${BUILD_EXTRA_YAP:-0}" = "1" ]; then
 47+        case "$LDLIBS" in
 48+                *-ltinfo*) ;;
 49+                *) LDLIBS="${LDLIBS} -ltinfo" ;;
 50+        esac
 51+fi
 52+
 53 BDIR="${ROOT}/.box"
 54 BOX="${ROOT}/aruu-box"
 55 LIBREDLINE="${ROOT}/shared/libredline/libredline.a"
 56@@ -114,101 +144,6 @@ compile_make() {
 57         printf '\t{ "make", make_main, "posix" },\n' >> "${BDIR}/entries_posix.inc"
 58 }
 59 
 60-compile_diff() {
 61-        ddir="${ROOT}/cmd/posix/diff"
 62-        [ -d "${ddir}" ] || return 0
 63-        symf="${BDIR}/diff.syms"
 64-        diff_objs=""
 65-
 66-        printf 'mkbox: cc diff (multi)\n'
 67-        for s in diff diffdir diffreg pr xmalloc; do
 68-                out="${BDIR}/diff_${s}.o"
 69-                eval "${CC} ${CPPFLAGS} -I\"\$ddir\" ${CFLAGS} -c \"\$ddir/\$s.c\" -o \"\$out\"" ||
 70-                        die "compile failed: diff/${s}.c"
 71-                diff_objs="${diff_objs} ${out}"
 72-        done
 73-
 74-        combined="${BDIR}/diff_combined.o"
 75-        ${LD:-ld} -r -o "${combined}" ${diff_objs} ||
 76-                die "ld -r failed: diff"
 77-
 78-        printf 'main diff_main\n' > "${symf}"
 79-        ${OBJCOPY} --redefine-syms="${symf}" "${combined}" ||
 80-                die "objcopy failed: diff"
 81-        ${OBJCOPY} --keep-global-symbol=diff_main "${combined}" ||
 82-                die "objcopy localize failed: diff"
 83-        rm -f "${symf}" ${diff_objs}
 84-
 85-        OBJS="${OBJS} ${combined}"
 86-        LDLIBS="${LDLIBS} -lm"
 87-        printf 'int diff_main(int, char **);\n' >> "${DECL_F}"
 88-        printf '\t{ "diff", diff_main, "posix" },\n' >> "${BDIR}/entries_posix.inc"
 89-}
 90-
 91-compile_patch() {
 92-        pdir="${ROOT}/cmd/posix/patch"
 93-        [ -d "${pdir}" ] || return 0
 94-        symf="${BDIR}/patch.syms"
 95-        patch_objs=""
 96-
 97-        printf 'mkbox: cc patch (multi)\n'
 98-        for s in patch pch inp util backupfile mkpath; do
 99-                out="${BDIR}/patch_${s}.o"
100-                eval "${CC} ${CPPFLAGS} -I\"\$pdir\" ${CFLAGS} -c \"\$pdir/\$s.c\" -o \"\$out\"" ||
101-                        die "compile failed: patch/${s}.c"
102-                patch_objs="${patch_objs} ${out}"
103-        done
104-
105-        combined="${BDIR}/patch_combined.o"
106-        ${LD:-ld} -r -o "${combined}" ${patch_objs} ||
107-                die "ld -r failed: patch"
108-
109-        printf 'main patch_main\n' > "${symf}"
110-        ${OBJCOPY} --redefine-syms="${symf}" "${combined}" ||
111-                die "objcopy failed: patch"
112-        ${OBJCOPY} --keep-global-symbol=patch_main "${combined}" ||
113-                die "objcopy localize failed: patch"
114-        rm -f "${symf}" ${patch_objs}
115-
116-        OBJS="${OBJS} ${combined}"
117-        printf 'int patch_main(int, char **);\n' >> "${DECL_F}"
118-        printf '\t{ "patch", patch_main, "posix" },\n' >> "${BDIR}/entries_posix.inc"
119-}
120-
121-compile_diff3() {
122-        ddir="${ROOT}/cmd/extra/diff3"
123-        [ -d "${ddir}" ] || return 0
124-        pdir="${ROOT}/cmd/posix/diff"
125-        symf="${BDIR}/diff3.syms"
126-        diff3_objs=""
127-
128-        printf 'mkbox: cc diff3 (multi)\n'
129-        for s in diff3; do
130-                out="${BDIR}/diff3_${s}.o"
131-                eval "${CC} ${CPPFLAGS} -I\"\$pdir\" ${CFLAGS} -c \"\$ddir/\$s.c\" -o \"\$out\"" ||
132-                        die "compile failed: diff3/${s}.c"
133-                diff3_objs="${diff3_objs} ${out}"
134-        done
135-        out="${BDIR}/diff3_xmalloc.o"
136-        eval "${CC} ${CPPFLAGS} -I\"\$pdir\" ${CFLAGS} -c \"\$pdir/xmalloc.c\" -o \"\$out\"" ||
137-                die "compile failed: diff/xmalloc.c"
138-        diff3_objs="${diff3_objs} ${out}"
139-
140-        combined="${BDIR}/diff3_combined.o"
141-        ${LD:-ld} -r -o "${combined}" ${diff3_objs} ||
142-                die "ld -r failed: diff3"
143-
144-        printf 'main diff3_main\n' > "${symf}"
145-        ${OBJCOPY} --redefine-syms="${symf}" "${combined}" ||
146-                die "objcopy failed: diff3"
147-        ${OBJCOPY} --keep-global-symbol=diff3_main "${combined}" ||
148-                die "objcopy localize failed: diff3"
149-        rm -f "${symf}" ${diff3_objs}
150-
151-        OBJS="${OBJS} ${combined}"
152-        printf 'int diff3_main(int, char **);\n' >> "${DECL_F}"
153-        printf '\t{ "diff3", diff3_main, "extra" },\n' >> "${BDIR}/entries_extra.inc"
154-}
155 
156 compile_yap() {
157         ydir="${ROOT}/cmd/extra/yap"
158@@ -239,11 +174,34 @@ compile_yap() {
159         rm -f "${symf}" ${yap_objs}
160 
161         OBJS="${OBJS} ${combined}"
162-        LDLIBS="${LDLIBS} -ltinfo"
163         printf 'int yap_main(int, char **);\n' >> "${DECL_F}"
164         printf '\t{ "yap", yap_main, "extra" },\n' >> "${BDIR}/entries_extra.inc"
165 }
166 
167+compile_bc() {
168+        bdir="${ROOT}/cmd/posix"
169+        symf="${BDIR}/bc.syms"
170+
171+        printf 'mkbox: yacc bc/bc.y\n'
172+        ${YACC} -o "${bdir}/bc.c" "${bdir}/bc.y" ||
173+                die "yacc failed: bc/bc.y"
174+
175+        out="${BDIR}/bc.o"
176+        eval "${CC} ${CPPFLAGS} ${CFLAGS} -c \"${bdir}/bc.c\" -o \"${out}\"" ||
177+                die "compile failed: bc/bc.c"
178+
179+        printf 'main bc_main\n' > "${symf}"
180+        ${OBJCOPY} --redefine-syms="${symf}" "${out}" ||
181+                die "objcopy failed: bc"
182+        ${OBJCOPY} --keep-global-symbol=bc_main "${out}" ||
183+                die "objcopy localize failed: bc"
184+        rm -f "${symf}" "${bdir}/bc.c"
185+
186+        OBJS="${OBJS} ${out}"
187+        printf 'int bc_main(int, char **);\n' >> "${DECL_F}"
188+        printf '\t{ "bc", bc_main, "posix" },\n' >> "${BDIR}/entries_posix.inc"
189+}
190+
191 compile_awk() {
192         adir="${ROOT}/cmd/posix/awk"
193         symf="${BDIR}/awk.syms"
194@@ -285,7 +243,6 @@ compile_awk() {
195         rm -f "${symf}" ${awk_objs}
196 
197         OBJS="${OBJS} ${combined}"
198-        LDLIBS="${LDLIBS} -lm"
199         printf 'int awk_main(int, char **);\n' >> "${DECL_F}"
200         printf '\t{ "awk", awk_main, "posix" },\n' >> "${BDIR}/entries_posix.inc"
201 }
202@@ -354,6 +311,18 @@ process_dir() {
203                 [ -f "${src}" ] || continue
204                 name=${src##*/}
205                 name=${name%.c}
206+
207+                # bc.c is generated by compile_bc() (see below); it lands in
208+                # this same directory but must not be picked up here too, or
209+                # bc_main ends up defined twice and the final link fails
210+                [ "${catg}" = "posix" ] && [ "${name}" = "bc" ] && continue
211+
212+                u_catg=$(printf '%s' "${catg}" | tr '[:lower:]' '[:upper:]')
213+                u_name=$(printf '%s' "${name}" | tr '[:lower:].-' '[:upper:]__')
214+                var_name="BUILD_${u_catg}_${u_name}"
215+                eval "val=\${$var_name:-0}"
216+                [ "$val" = "1" ] || continue
217+
218                 fn=$(printf '%s' "${name}" | tr '.-' '__')
219                 compile_tool "${src}" "${name}" "${fn}" "${catg}" "${extra}"
220                 if [ "${name}" = "test" ]; then
221@@ -365,31 +334,29 @@ process_dir() {
222         done
223 }
224 
225-[ -f "${ROOT}/cmd/posix/diff.c" ] && LDLIBS="${LDLIBS} -lm"
226-
227 process_dir "${ROOT}/cmd/posix" "posix"
228-compile_diff
229-compile_patch
230-compile_awk
231-compile_sh
232-compile_make
233+[ "${BUILD_POSIX_AWK:-0}" = "1" ] && compile_awk
234+[ "${BUILD_POSIX_BC:-0}" = "1" ] && compile_bc
235+[ "${BUILD_POSIX_SH:-0}" = "1" ] && compile_sh
236+[ "${BUILD_POSIX_MAKE:-0}" = "1" ] && compile_make
237 process_dir "${ROOT}/cmd/linux" "linux"
238 process_dir "${ROOT}/cmd/net" "net"
239 process_dir "${ROOT}/cmd/pseudo" "pseudo"
240 process_dir "${ROOT}/cmd/xsi" "xsi"
241 process_dir "${ROOT}/cmd/extra" "extra"
242-compile_diff3
243-compile_yap
244+[ "${BUILD_EXTRA_YAP:-0}" = "1" ] && compile_yap
245 
246 DISP="${BDIR}/aruu-box.c"
247 printf 'mkbox: generating dispatch\n'
248 
249-cat > "${DISP}" << 'DISPATCH_HEAD'
250-/* This software is released into the public domain, or
251-   registered under the ISC License, see ./LICENSE for details
252-   2026 xplshn [anto@xplshn.com.ar](mailto:anto@xplshn.com.ar) */
253+escaped_license=$(tr -d '\r' < "${ROOT}/LICENSE" | sed 's/\\/\\\\/g; s/"/\\"/g; s/^/\"/; s/$/\\n\"/')
254+
255+cat > "${DISP}" << DISPATCH_HEAD
256+/* this software is released into the public domain, or
257+   registered under the isc license, see ./license for details
258+   2026 xplshn anto@xplshn.com.ar */
259 
260-/* routes argv[0] to the appropriate tool main */
261+/* routes argv0 to the appropriate tool main */
262 #include "wexec.h"
263 #include "util.h"
264 
265@@ -398,6 +365,10 @@ cat > "${DISP}" << 'DISPATCH_HEAD'
266 #include <string.h>
267 #include <unistd.h>
268 
269+static const char license[] =
270+${escaped_license}
271+;
272+
273 extern char *argv0;
274 
275 DISPATCH_HEAD
276@@ -436,7 +407,7 @@ usage(void)
277 
278         last = NULL;
279         col = 0;
280-        fprintf(stderr, "usage: %s [-i path] [command [args...]]\n", argv0);
281+        fprintf(stderr, "usage: %s [-i path] [--license | -l] [command [args...]]\n", argv0);
282         for (c = cmds; c->name; c++) {
283                 if (!last || strcmp(c->cat, last) != 0) {
284                         if (last)
285@@ -498,6 +469,10 @@ main(int argc, char *argv[])
286         if (strcmp(s, "aruu-box") == 0) {
287                 if (argc < 2)
288                         usage();
289+                if (strcmp(argv[1], "--license") == 0 || strcmp(argv[1], "-l") == 0) {
290+                        printf("%s", license);
291+                        return 0;
292+                }
293                 argc--;
294                 argv++;
295                 if (strcmp(argv[0], "-i") == 0) {
+15, -32
  1@@ -10,17 +10,17 @@ import (
  2 	"time"
  3 )
  4 
  5-// parse config.mk variables and values
  6+// parse config.kv variables and values
  7 type Config map[string]string
  8 
  9-func parseConfigMk(path string) (Config, error) {
 10+func parseConfigKv(path string) (Config, error) {
 11 	f, err := os.Open(path)
 12 	if err != nil {
 13 		return nil, err
 14 	}
 15 	defer f.Close()
 16 
 17-	raw := make(Config)
 18+	cfg := make(Config)
 19 	sc := bufio.NewScanner(f)
 20 	for sc.Scan() {
 21 		line := strings.TrimSpace(sc.Text())
 22@@ -33,40 +33,18 @@ func parseConfigMk(path string) (Config, error) {
 23 		}
 24 		k := strings.TrimSpace(line[:eq])
 25 		v := strings.TrimSpace(line[eq+1:])
 26-		raw[k] = v
 27+		if len(v) >= 2 && ((v[0] == '"' && v[len(v)-1] == '"') || (v[0] == '\'' && v[len(v)-1] == '\'')) {
 28+			v = v[1 : len(v)-1]
 29+		}
 30+		cfg[k] = v
 31 	}
 32 	if err := sc.Err(); err != nil {
 33 		return nil, err
 34 	}
 35 
 36-	cfg := make(Config, len(raw))
 37-	for k, v := range raw {
 38-		cfg[k] = expandVars(v, raw)
 39-	}
 40 	return cfg, nil
 41 }
 42 
 43-func expandVars(s string, env Config) string {
 44-	for {
 45-		start := strings.Index(s, "$(")
 46-		if start < 0 {
 47-			break
 48-		}
 49-		end := strings.Index(s[start:], ")")
 50-		if end < 0 {
 51-			break
 52-		}
 53-		end += start
 54-		varname := s[start+2 : end]
 55-		replacement := ""
 56-		if v, ok := env[varname]; ok {
 57-			replacement = v
 58-		}
 59-		s = s[:start] + replacement + s[end+1:]
 60-	}
 61-	return s
 62-}
 63-
 64 func (cfg Config) isEnabled(key string) bool {
 65 	return cfg[key] == "1"
 66 }
 67@@ -154,6 +132,11 @@ func inferSection(path string) int {
 68 		strings.Contains(clean, "/net/"),
 69 		strings.Contains(clean, "/xsi/"):
 70 		return 8
 71+	case strings.Contains(clean, "/posix/"),
 72+		strings.Contains(clean, "/pseudo/"),
 73+		strings.Contains(clean, "/extra/"),
 74+		strings.Contains(clean, "/dev/"):
 75+		return 1
 76 	default:
 77 		return 1
 78 	}
 79@@ -177,19 +160,19 @@ func newRenderer(format string, page *Page) (Renderer, error) {
 80 
 81 // main entry point and flags definition
 82 func main() {
 83-	configPath := flag.String("config", "config.mk", "path to config.mk")
 84+	configPath := flag.String("config", "scripts/mk/config.kv", "path to config.kv")
 85 	sectionFlag := flag.Int("section", 0, "man section override (0 = infer from path)")
 86 	dateFlag := flag.String("date", "", "date string for TH line (default: current month/year)")
 87 	formatFlag := flag.String("fmt", "mdoc", "output format: mdoc or txt")
 88 	flag.Parse()
 89 
 90 	if flag.NArg() < 1 {
 91-		fmt.Fprintf(os.Stderr, "usage: mkman [-config config.mk] [-section N] [-fmt mdoc|txt] file.c\n")
 92+		fmt.Fprintf(os.Stderr, "usage: mkman [-config scripts/mk/config.kv] [-section N] [-fmt mdoc|txt] file.c\n")
 93 		os.Exit(1)
 94 	}
 95 	cfile := flag.Arg(0)
 96 
 97-	cfg, err := parseConfigMk(*configPath)
 98+	cfg, err := parseConfigKv(*configPath)
 99 	if err != nil {
100 		fmt.Fprintf(os.Stderr, "mkman: config: %v\n", err)
101 		os.Exit(1)
+11, -1
 1@@ -43,8 +43,18 @@ func extractManLines(path string, cfg Config) ([]string, error) {
 2 		trimmed := strings.TrimSpace(line)
 3 
 4 		if inBlockComment {
 5-			if trimmed == "*/" || trimmed == "* /" {
 6+			if strings.Contains(trimmed, "*/") {
 7 				inBlockComment = false
 8+				idx := strings.Index(trimmed, "*/")
 9+				before := strings.TrimSpace(trimmed[:idx])
10+				if strings.HasPrefix(before, "* ") {
11+					before = before[2:]
12+				} else if before == "*" {
13+					before = ""
14+				}
15+				if before != "" {
16+					lines = append(lines, stripManPrefix(before))
17+				}
18 				continue
19 			}
20 
+3, -0
1@@ -121,3 +121,6 @@
2 #ifndef FEATURE_INPROC_EXEC
3 #define FEATURE_INPROC_EXEC 0
4 #endif
5+#ifndef FEATURE_INPROC_EXEC_OVERRIDE
6+#define FEATURE_INPROC_EXEC_OVERRIDE 0
7+#endif
+101, -7
  1@@ -8,6 +8,7 @@
  2 #include <signal.h>
  3 #include <stdlib.h>
  4 #include <string.h>
  5+#include <sys/stat.h>
  6 #include <sys/wait.h>
  7 #include <unistd.h>
  8 
  9@@ -84,6 +85,99 @@ wexec_is_builtin(const char *name)
 10   return 0;
 11 }
 12 
 13+#if FEATURE_INPROC_EXEC
 14+static int inproc_enabled  = 1;
 15+
 16+#if FEATURE_INPROC_EXEC_OVERRIDE
 17+static int inproc_env_read = 0;
 18+
 19+/* ARUU_INPROC_EXEC=0 forces fork+exec at runtime, even though the box was
 20+ * built with FEATURE_INPROC_EXEC=1. lets a person reach an external tool
 21+ * that shares a name with a builtin without giving its full path. only
 22+ * compiled in when the box is also built with FEATURE_INPROC_EXEC_OVERRIDE=1;
 23+ * without that flag this env var is never read and inproc dispatch cannot be
 24+ * bypassed except through an explicit wexec_set_inproc() call. read once
 25+ * and cached, an explicit wexec_set_inproc() call overrides it */
 26+static void
 27+inproc_read_env(void)
 28+{
 29+  const char *e;
 30+
 31+  if (inproc_env_read)
 32+    return;
 33+  inproc_env_read = 1;
 34+  e = getenv("ARUU_INPROC_EXEC");
 35+  if (e && strcmp(e, "0") == 0)
 36+    inproc_enabled = 0;
 37+}
 38+#endif
 39+
 40+void
 41+wexec_set_inproc(int enabled)
 42+{
 43+#if FEATURE_INPROC_EXEC_OVERRIDE
 44+  inproc_env_read = 1;
 45+#endif
 46+  inproc_enabled = enabled;
 47+}
 48+
 49+int
 50+wexec_get_inproc(void)
 51+{
 52+#if FEATURE_INPROC_EXEC_OVERRIDE
 53+  inproc_read_env();
 54+#endif
 55+  return inproc_enabled;
 56+}
 57+#endif
 58+
 59+char *
 60+wwhich(const char *name)
 61+{
 62+  const char *path, *p, *end;
 63+  char       *buf;
 64+  size_t      dlen, nlen;
 65+  struct stat  st;
 66+
 67+#if FEATURE_INPROC_EXEC
 68+  /* when inproc dispatch is active, registered builtins have no filesystem path */
 69+  if (inproc_enabled && wexec_is_builtin(name))
 70+    return NULL;
 71+#endif
 72+
 73+  /* slash present: treat as a literal path */
 74+  if (strchr(name, '/') != NULL) {
 75+    if (stat(name, &st) == 0 && S_ISREG(st.st_mode) && (st.st_mode & 0111))
 76+      return estrdup(name);
 77+    return NULL;
 78+  }
 79+
 80+  path = getenv("PATH");
 81+  if (path == NULL)
 82+    path = "/usr/local/bin:/usr/bin:/bin";
 83+
 84+  nlen = strlen(name);
 85+  p    = path;
 86+  for (;;) {
 87+    end  = strchr(p, ':');
 88+    dlen = end ? (size_t)(end - p) : strlen(p);
 89+    /* skip empty components (current dir) for safety */
 90+    if (dlen > 0) {
 91+      buf           = emalloc(dlen + 1 + nlen + 1);
 92+      memcpy(buf, p, dlen);
 93+      buf[dlen]     = '/';
 94+      memcpy(buf + dlen + 1, name, nlen + 1);
 95+      if (stat(buf, &st) == 0 && S_ISREG(st.st_mode) && (st.st_mode & 0111))
 96+        return buf;
 97+      free(buf);
 98+    }
 99+    if (!end)
100+      break;
101+    p = end + 1;
102+  }
103+  return NULL;
104+}
105+
106 #if FEATURE_INPROC_EXEC
107 static int
108 call_builtin(const char *name, char *const *argv)
109@@ -138,7 +232,7 @@ int
110 wexecvp(const char *name, char *const *argv)
111 {
112 #if FEATURE_INPROC_EXEC
113-  if (wexec_is_builtin(name)) {
114+  if (inproc_enabled && wexec_is_builtin(name)) {
115     fflush(stdout);
116     fflush(stderr);
117     return call_builtin(name, argv);
118@@ -154,7 +248,7 @@ wexecv(const char *path, char *const *argv)
119   {
120     const char *base = strrchr(path, '/');
121     base             = base ? base + 1 : path;
122-    if (wexec_is_builtin(base)) {
123+    if (inproc_enabled && wexec_is_builtin(base)) {
124       fflush(stdout);
125       fflush(stderr);
126       return call_builtin(base, argv);
127@@ -201,7 +295,7 @@ wpopen(const char *name, char *const *argv, const char *mode)
128     }
129     if (argv) {
130 #if FEATURE_INPROC_EXEC
131-      if (wexec_is_builtin(name)) {
132+      if (inproc_enabled && wexec_is_builtin(name)) {
133         int    argc;
134         char **p;
135         argc = 0;
136@@ -221,7 +315,7 @@ wpopen(const char *name, char *const *argv, const char *mode)
137       sh_argv[2] = (char *)name;
138       sh_argv[3] = NULL;
139 #if FEATURE_INPROC_EXEC
140-      if (wexec_is_builtin("sh")) {
141+      if (inproc_enabled && wexec_is_builtin("sh")) {
142         call_builtin("sh", sh_argv);
143         fflush(stdout);
144         fflush(stderr);
145@@ -279,7 +373,7 @@ int
146 wsystem(const char *cmd)
147 {
148 #if FEATURE_INPROC_EXEC
149-  if (wexec_is_builtin("sh")) {
150+  if (inproc_enabled && wexec_is_builtin("sh")) {
151     char *sh_argv[4];
152     sh_argv[0] = "sh";
153     sh_argv[1] = "-c";
154@@ -304,7 +398,7 @@ void
155 wexecvp_self(const char *name, char *const *argv)
156 {
157 #if FEATURE_INPROC_EXEC
158-  if (wexec_is_builtin(name)) {
159+  if (inproc_enabled && wexec_is_builtin(name)) {
160     int ret;
161     fflush(stdout);
162     fflush(stderr);
163@@ -326,7 +420,7 @@ wexecv_self(const char *path, char *const *argv)
164   {
165     const char *base = strrchr(path, '/');
166     base             = base ? base + 1 : path;
167-    if (wexec_is_builtin(base)) {
168+    if (inproc_enabled && wexec_is_builtin(base)) {
169       int ret;
170       fflush(stdout);
171       fflush(stderr);
+17, -0
 1@@ -10,6 +10,23 @@ typedef int (*wexec_fn)(int argc, char **argv);
 2 int wexec_register(const char *name, wexec_fn fn);
 3 int wexec_is_builtin(const char *name);
 4 
 5+/* search PATH for name; returns emalloc'd absolute path or NULL if not found.
 6+ * when FEATURE_INPROC_EXEC is compiled in and inproc dispatch is enabled,
 7+ * returns NULL for registered builtins (they have no filesystem path). */
 8+char *wwhich(const char *name);
 9+
10+#if FEATURE_INPROC_EXEC
11+/* runtime toggle: disable to force fork+exec even when builtins are registered.
12+ * when the box is also built with FEATURE_INPROC_EXEC_OVERRIDE=1,
13+ * wexec_get_inproc() additionally honors ARUU_INPROC_EXEC=0 from the
14+ * environment, read once on first use, so a builtin can be bypassed without
15+ * a rebuild. without that second flag, inproc dispatch is hardwired on for
16+ * the whole process and only an explicit wexec_set_inproc() call can
17+ * change it. */
18+void wexec_set_inproc(int enabled);
19+int  wexec_get_inproc(void);
20+#endif
21+
22 int wexecvp(const char *name, char *const *argv);
23 int wexecv(const char *path, char *const *argv);
24