aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-04-30 21:46:45 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-04-30 21:46:45 +0000
commit002447e6743cd0bc31901c7bd3049a4f7f5cc1fc (patch)
treeed9a1780a9a8153e4ed90a29c96dde9fb4742ca7
parented2583c548119932127886e58bf7a97f48bf3316 (diff)
parent7c075dd489f6d53217c2656b20ef619230baa367 (diff)
downloadtoybox-build-tools-release.tar.gz
Snap for 11784721 from 7c075dd489f6d53217c2656b20ef619230baa367 to build-tools-releasebuild-tools-release
Change-Id: I0caf571c445953dc2c523bab6c66385c63299180
-rw-r--r--.gitignore18
-rw-r--r--Android.bp1
-rw-r--r--METADATA6
-rw-r--r--Makefile2
-rw-r--r--android/device/generated/config.h2
-rw-r--r--android/device/generated/help.h2
-rw-r--r--android/device/generated/newtoys.h2
-rw-r--r--android/linux/generated/config.h2
-rw-r--r--android/linux/generated/help.h2
-rw-r--r--android/linux/generated/newtoys.h2
-rw-r--r--android/mac/generated/config.h2
-rw-r--r--android/mac/generated/help.h2
-rw-r--r--android/mac/generated/newtoys.h2
-rw-r--r--kconfig/freebsd_miniconfig1
-rw-r--r--lib/args.c11
-rw-r--r--lib/lib.h2
-rw-r--r--lib/password.c2
-rw-r--r--lib/portability.c2
-rw-r--r--lib/tty.c40
-rwxr-xr-xmkroot/mkroot.sh151
-rwxr-xr-xmkroot/packages/tests3
-rwxr-xr-xmkroot/record-commands33
-rwxr-xr-xmkroot/tar-for-web.sh8
-rwxr-xr-xscripts/make.sh6
-rwxr-xr-xscripts/mcm-buildall.sh11
-rwxr-xr-xscripts/prereq/build.sh15
-rw-r--r--scripts/prereq/generated/config.h706
-rw-r--r--scripts/prereq/generated/flags.h827
-rw-r--r--scripts/prereq/generated/globals.h155
-rw-r--r--scripts/prereq/generated/help.h33
-rw-r--r--scripts/prereq/generated/newtoys.h123
-rw-r--r--scripts/prereq/generated/tags.h1
-rwxr-xr-xscripts/probes/cmd2dpkg26
-rwxr-xr-xscripts/recreate-prereq.sh41
-rwxr-xr-x[-rw-r--r--]tests/fold.test0
-rwxr-xr-xtests/timeout.test8
-rwxr-xr-x[-rw-r--r--]tests/touch.test0
-rw-r--r--toys.h2
-rw-r--r--toys/other/inotifyd.c3
-rw-r--r--toys/other/watch.c20
-rw-r--r--www/faq.html2
-rw-r--r--www/header.html2
-rw-r--r--www/news.html298
-rw-r--r--www/roadmap.html262
44 files changed, 2586 insertions, 253 deletions
diff --git a/.gitignore b/.gitignore
index 43a79349..2b74ad14 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,10 +1,10 @@
syntax: glob
-.config*
-.single*
-change/
-generated/
-kconfig/mconf
-kconfig/conf
-kconfig/*.c
-toybox
-toybox_unstripped
+/.config*
+/.single*
+/change/
+/generated/
+/kconfig/mconf
+/kconfig/conf
+/kconfig/*.c
+/toybox
+/toybox_unstripped
diff --git a/Android.bp b/Android.bp
index f4791fbc..5d9ec2eb 100644
--- a/Android.bp
+++ b/Android.bp
@@ -294,6 +294,7 @@ toybox_symlinks = [
"getconf",
"getenforce",
"getfattr",
+ "getopt",
"gpiodetect",
"gpiofind",
"gpioget",
diff --git a/METADATA b/METADATA
index af5fd034..8730ee22 100644
--- a/METADATA
+++ b/METADATA
@@ -8,13 +8,13 @@ third_party {
license_type: UNENCUMBERED
last_upgrade_date {
year: 2024
- month: 3
- day: 25
+ month: 4
+ day: 22
}
homepage: "https://landley.net/toybox/"
identifier {
type: "Git"
value: "https://github.com/landley/toybox"
- version: "95906a13d1c6d0df5f521d2d91371791663f339e"
+ version: "7c6aecd477a9b898df981197088c9e1d5775fe9c"
}
}
diff --git a/Makefile b/Makefile
index 100fd30e..09fed076 100644
--- a/Makefile
+++ b/Makefile
@@ -64,7 +64,7 @@ root_clean:
@echo root cleaned
clean::
- @chmod -fR 700 generated || true
+ @chmod -fR 700 generated 2>/dev/null || true
@rm -rf toybox generated change install .singleconfig*
@echo cleaned
diff --git a/android/device/generated/config.h b/android/device/generated/config.h
index 903901ee..7dca3830 100644
--- a/android/device/generated/config.h
+++ b/android/device/generated/config.h
@@ -28,6 +28,8 @@
#define USE_TOYBOX_SMACK(...)
#define CFG_TOYBOX_SUID 0
#define USE_TOYBOX_SUID(...)
+#define CFG_TOYBOX_UID_SYS 100
+#define CFG_TOYBOX_UID_USR 500
#define CFG_TOYBOX_ZHELP 0
#define USE_TOYBOX_ZHELP(...)
#define CFG_ACPI 1
diff --git a/android/device/generated/help.h b/android/device/generated/help.h
index 44ce000a..74661d3d 100644
--- a/android/device/generated/help.h
+++ b/android/device/generated/help.h
@@ -146,7 +146,7 @@
#define HELP_watchdog "usage: watchdog [-F] [-t UPDATE] [-T DEADLINE] DEV\n\nStart the watchdog timer at DEV with optional timeout parameters.\n\n-F run in the foreground (do not daemonize)\n-t poke watchdog every UPDATE seconds (default 4)\n-T reboot if not poked for DEADLINE seconds (default 60)"
-#define HELP_watch "usage: watch [-tebx] [-n SEC] PROG ARGS\n\nRun PROG every -n seconds, showing output. Hit q to quit.\n\n-n Loop period in seconds (default 2)\n-t Don't print header\n-e Exit on error\n-b Beep on command error\n-x Exec command directly (vs \"sh -c\")"
+#define HELP_watch "usage: watch [-tebx] [-n SEC] COMMAND...\n\nRun COMMAND every -n seconds, showing output that fits terminal, q to quit.\n\n-n Number of seconds between repeats (default 2.0)\n-t Don't print header\n-e Exit on error\n-b Beep on command error\n-x Exec command directly (without \"sh -c\")"
#define HELP_w "usage: w\n\nShow who is logged on and since how long they logged in."
diff --git a/android/device/generated/newtoys.h b/android/device/generated/newtoys.h
index 23119eca..92814854 100644
--- a/android/device/generated/newtoys.h
+++ b/android/device/generated/newtoys.h
@@ -141,7 +141,7 @@ USE_ICONV(NEWTOY(iconv, "cst:f:", TOYFLAG_USR|TOYFLAG_BIN))
USE_ID(NEWTOY(id, ">1"USE_ID_Z("Z")"nGgru[!"USE_ID_Z("Z")"Ggu]", TOYFLAG_USR|TOYFLAG_BIN))
USE_IFCONFIG(NEWTOY(ifconfig, "^?aS", TOYFLAG_SBIN))
USE_INIT(NEWTOY(init, "", TOYFLAG_SBIN))
-USE_INOTIFYD(NEWTOY(inotifyd, "<2", TOYFLAG_USR|TOYFLAG_BIN))
+USE_INOTIFYD(NEWTOY(inotifyd, "<2", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
USE_INSMOD(NEWTOY(insmod, "<1", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
USE_INSTALL(NEWTOY(install, "<1cdDp(preserve-timestamps)svt:m:o:g:", TOYFLAG_USR|TOYFLAG_BIN))
USE_IONICE(NEWTOY(ionice, "^tc#<0>3=2n#<0>7=5p#", TOYFLAG_USR|TOYFLAG_BIN))
diff --git a/android/linux/generated/config.h b/android/linux/generated/config.h
index 737e2dc2..3e2afb23 100644
--- a/android/linux/generated/config.h
+++ b/android/linux/generated/config.h
@@ -28,6 +28,8 @@
#define USE_TOYBOX_SMACK(...)
#define CFG_TOYBOX_SUID 0
#define USE_TOYBOX_SUID(...)
+#define CFG_TOYBOX_UID_SYS 100
+#define CFG_TOYBOX_UID_USR 500
#define CFG_TOYBOX_ZHELP 0
#define USE_TOYBOX_ZHELP(...)
#define CFG_ACPI 0
diff --git a/android/linux/generated/help.h b/android/linux/generated/help.h
index 4f80dbc8..b3c74b17 100644
--- a/android/linux/generated/help.h
+++ b/android/linux/generated/help.h
@@ -148,7 +148,7 @@
#define HELP_watchdog "usage: watchdog [-F] [-t UPDATE] [-T DEADLINE] DEV\n\nStart the watchdog timer at DEV with optional timeout parameters.\n\n-F run in the foreground (do not daemonize)\n-t poke watchdog every UPDATE seconds (default 4)\n-T reboot if not poked for DEADLINE seconds (default 60)"
-#define HELP_watch "usage: watch [-tebx] [-n SEC] PROG ARGS\n\nRun PROG every -n seconds, showing output. Hit q to quit.\n\n-n Loop period in seconds (default 2)\n-t Don't print header\n-e Exit on error\n-b Beep on command error\n-x Exec command directly (vs \"sh -c\")"
+#define HELP_watch "usage: watch [-tebx] [-n SEC] COMMAND...\n\nRun COMMAND every -n seconds, showing output that fits terminal, q to quit.\n\n-n Number of seconds between repeats (default 2.0)\n-t Don't print header\n-e Exit on error\n-b Beep on command error\n-x Exec command directly (without \"sh -c\")"
#define HELP_w "usage: w\n\nShow who is logged on and since how long they logged in."
diff --git a/android/linux/generated/newtoys.h b/android/linux/generated/newtoys.h
index 23119eca..92814854 100644
--- a/android/linux/generated/newtoys.h
+++ b/android/linux/generated/newtoys.h
@@ -141,7 +141,7 @@ USE_ICONV(NEWTOY(iconv, "cst:f:", TOYFLAG_USR|TOYFLAG_BIN))
USE_ID(NEWTOY(id, ">1"USE_ID_Z("Z")"nGgru[!"USE_ID_Z("Z")"Ggu]", TOYFLAG_USR|TOYFLAG_BIN))
USE_IFCONFIG(NEWTOY(ifconfig, "^?aS", TOYFLAG_SBIN))
USE_INIT(NEWTOY(init, "", TOYFLAG_SBIN))
-USE_INOTIFYD(NEWTOY(inotifyd, "<2", TOYFLAG_USR|TOYFLAG_BIN))
+USE_INOTIFYD(NEWTOY(inotifyd, "<2", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
USE_INSMOD(NEWTOY(insmod, "<1", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
USE_INSTALL(NEWTOY(install, "<1cdDp(preserve-timestamps)svt:m:o:g:", TOYFLAG_USR|TOYFLAG_BIN))
USE_IONICE(NEWTOY(ionice, "^tc#<0>3=2n#<0>7=5p#", TOYFLAG_USR|TOYFLAG_BIN))
diff --git a/android/mac/generated/config.h b/android/mac/generated/config.h
index b06bd580..c395991f 100644
--- a/android/mac/generated/config.h
+++ b/android/mac/generated/config.h
@@ -28,6 +28,8 @@
#define USE_TOYBOX_SMACK(...)
#define CFG_TOYBOX_SUID 0
#define USE_TOYBOX_SUID(...)
+#define CFG_TOYBOX_UID_SYS 100
+#define CFG_TOYBOX_UID_USR 500
#define CFG_TOYBOX_ZHELP 0
#define USE_TOYBOX_ZHELP(...)
#define CFG_ACPI 0
diff --git a/android/mac/generated/help.h b/android/mac/generated/help.h
index 4f80dbc8..b3c74b17 100644
--- a/android/mac/generated/help.h
+++ b/android/mac/generated/help.h
@@ -148,7 +148,7 @@
#define HELP_watchdog "usage: watchdog [-F] [-t UPDATE] [-T DEADLINE] DEV\n\nStart the watchdog timer at DEV with optional timeout parameters.\n\n-F run in the foreground (do not daemonize)\n-t poke watchdog every UPDATE seconds (default 4)\n-T reboot if not poked for DEADLINE seconds (default 60)"
-#define HELP_watch "usage: watch [-tebx] [-n SEC] PROG ARGS\n\nRun PROG every -n seconds, showing output. Hit q to quit.\n\n-n Loop period in seconds (default 2)\n-t Don't print header\n-e Exit on error\n-b Beep on command error\n-x Exec command directly (vs \"sh -c\")"
+#define HELP_watch "usage: watch [-tebx] [-n SEC] COMMAND...\n\nRun COMMAND every -n seconds, showing output that fits terminal, q to quit.\n\n-n Number of seconds between repeats (default 2.0)\n-t Don't print header\n-e Exit on error\n-b Beep on command error\n-x Exec command directly (without \"sh -c\")"
#define HELP_w "usage: w\n\nShow who is logged on and since how long they logged in."
diff --git a/android/mac/generated/newtoys.h b/android/mac/generated/newtoys.h
index 23119eca..92814854 100644
--- a/android/mac/generated/newtoys.h
+++ b/android/mac/generated/newtoys.h
@@ -141,7 +141,7 @@ USE_ICONV(NEWTOY(iconv, "cst:f:", TOYFLAG_USR|TOYFLAG_BIN))
USE_ID(NEWTOY(id, ">1"USE_ID_Z("Z")"nGgru[!"USE_ID_Z("Z")"Ggu]", TOYFLAG_USR|TOYFLAG_BIN))
USE_IFCONFIG(NEWTOY(ifconfig, "^?aS", TOYFLAG_SBIN))
USE_INIT(NEWTOY(init, "", TOYFLAG_SBIN))
-USE_INOTIFYD(NEWTOY(inotifyd, "<2", TOYFLAG_USR|TOYFLAG_BIN))
+USE_INOTIFYD(NEWTOY(inotifyd, "<2", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
USE_INSMOD(NEWTOY(insmod, "<1", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
USE_INSTALL(NEWTOY(install, "<1cdDp(preserve-timestamps)svt:m:o:g:", TOYFLAG_USR|TOYFLAG_BIN))
USE_IONICE(NEWTOY(ionice, "^tc#<0>3=2n#<0>7=5p#", TOYFLAG_USR|TOYFLAG_BIN))
diff --git a/kconfig/freebsd_miniconfig b/kconfig/freebsd_miniconfig
index e82e3f95..0ca16d89 100644
--- a/kconfig/freebsd_miniconfig
+++ b/kconfig/freebsd_miniconfig
@@ -61,6 +61,7 @@ CONFIG_TOUCH=y
CONFIG_TRUE=y
CONFIG_TSORT=y
CONFIG_TTY=y
+CONFIG_UNAME=y
CONFIG_UNIQ=y
CONFIG_UNLINK=y
CONFIG_UUDECODE=y
diff --git a/lib/args.c b/lib/args.c
index c5ba4505..9b94521d 100644
--- a/lib/args.c
+++ b/lib/args.c
@@ -206,12 +206,13 @@ static void gotflag(struct getoptflagstate *gof, struct opts *opt, int longopt)
while (*list) list=&((*list)->next);
*list = xzalloc(sizeof(struct arg_list));
(*list)->arg = arg;
- } else if (type == '#' || type == '-') {
- long long l = atolx(arg);
+ } else if (type == '#' || type == '-' || type == '%') {
+ long long l = (type == '%') ? xparsemillitime(arg) : atolx(arg);
if (type == '-' && !ispunct(*arg)) l*=-1;
- if (l < opt->val[0].l) help_exit("-%c < %ld", opt->c, opt->val[0].l);
- if (l > opt->val[1].l) help_exit("-%c > %ld", opt->c, opt->val[1].l);
+ arg = (type == '%') ? "ms" : "";
+ if (l < opt->val[0].l) help_exit("-%c < %ld%s", opt->c, opt->val[0].l, arg);
+ if (l > opt->val[1].l) help_exit("-%c > %ld%s", opt->c, opt->val[1].l, arg);
*(opt->arg) = l;
} else if (CFG_TOYBOX_FLOAT && type == '.') {
@@ -222,7 +223,7 @@ static void gotflag(struct getoptflagstate *gof, struct opts *opt, int longopt)
help_exit("-%c < %lf", opt->c, (double)opt->val[0].f);
if (opt->val[1].l != LONG_MAX && *f > opt->val[1].f)
help_exit("-%c > %lf", opt->c, (double)opt->val[1].f);
- } else if (type=='%') *(opt->arg) = xparsemillitime(arg);
+ }
}
// Parse this command's options string into struct getoptflagstate, which
diff --git a/lib/lib.h b/lib/lib.h
index da20dd10..4618a2f0 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -333,6 +333,8 @@ int terminal_probesize(unsigned *xx, unsigned *yy);
#define KEY_ALT (1<<18)
int scan_key(char *scratch, int timeout_ms);
int scan_key_getsize(char *scratch, int timeout_ms, unsigned *xx, unsigned *yy);
+unsigned cfspeed2bps(unsigned speed);
+unsigned bps2cfspeed(unsigned baud);
void xsetspeed(struct termios *tio, int speed);
int set_terminal(int fd, int raw, int speed, struct termios *old);
void xset_terminal(int fd, int raw, int speed, struct termios *old);
diff --git a/lib/password.c b/lib/password.c
index f653e41d..461b4118 100644
--- a/lib/password.c
+++ b/lib/password.c
@@ -56,6 +56,7 @@ int read_password(char *buf, int buflen, char *mesg)
int i, tty = tty_fd(), ret = 1;
// Set NOP signal handler to return from the read.
+ fflush(0);
sigaction(SIGINT, &sa, &oldsa);
tcflush(tty, TCIFLUSH);
xset_terminal(tty, 1, 0, &oldtermio);
@@ -77,6 +78,7 @@ int read_password(char *buf, int buflen, char *mesg)
tcsetattr(0, TCSANOW, &oldtermio);
sigaction(SIGINT, &oldsa, 0);
xputc('\n');
+ fflush(0);
buf[i*!ret] = 0;
return ret;
diff --git a/lib/portability.c b/lib/portability.c
index 83382d1d..abcecc80 100644
--- a/lib/portability.c
+++ b/lib/portability.c
@@ -65,7 +65,7 @@ struct mtab_list *xgetmountlist(char *path)
int i, count;
if (path) error_exit("xgetmountlist");
- if ((count = getmntinfo(&entries, 0)) == 0) perror_exit("getmntinfo");
+ if (!(count = getmntinfo(&entries, MNT_WAIT))) perror_exit("getmntinfo");
// The "test" part of the loop is done before the first time through and
// again after each "increment", so putting the actual load there avoids
diff --git a/lib/tty.c b/lib/tty.c
index 543006fb..7c249fcc 100644
--- a/lib/tty.c
+++ b/lib/tty.c
@@ -16,6 +16,7 @@
#include "toys.h"
+// Check stdout, stderr, stdin (in that order) and if none open /dev/tty
int tty_fd(void)
{
int i, j;
@@ -72,19 +73,38 @@ int terminal_probesize(unsigned *xx, unsigned *yy)
return 0;
}
-void xsetspeed(struct termios *tio, int speed)
+// This table skips both B0 and BOTHER
+static const int speeds[] = {50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800,
+ 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 500000, 576000,
+ 921600, 1000000, 1152000, 1500000, 2000000, 2500000, 3000000,3500000,4000000};
+
+// Show bits per second for cfspeed value. Assumes we have a valid speed
+unsigned cfspeed2bps(unsigned speed)
{
- int i, speeds[] = {50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400,
- 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800,
- 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
- 2500000, 3000000, 3500000, 4000000};
-
- // Find speed in table, adjust to constant
- for (i = 0; i < ARRAY_LEN(speeds); i++) if (speeds[i] == speed) break;
- if (i == ARRAY_LEN(speeds)) error_exit("unknown speed: %d", speed);
- cfsetspeed(tio, i+1+4081*(i>15));
+ if (!(speed&15)) return 0;
+ if (speed>15) speed = (speed&15)+15;
+
+ return speeds[--speed];
}
+// Convert bits per second to cfspeed value. Returns 0 for unknown bps
+unsigned bps2cfspeed(unsigned baud)
+{
+ int i = 0;
+
+ while (i<ARRAY_LEN(speeds))
+ if (speeds[i++]==baud) return i+(i>15)*(4096-16+1);
+
+ return 0;
+}
+
+void xsetspeed(struct termios *tio, int bps)
+{
+ int i = bps2cfspeed(bps);
+
+ if (!i) error_exit("unknown speed: %d", bps);
+ cfsetspeed(tio, i);
+}
// Reset terminal to known state, saving copy of old state if old != NULL.
int set_terminal(int fd, int raw, int speed, struct termios *old)
diff --git a/mkroot/mkroot.sh b/mkroot/mkroot.sh
index 37a91642..227dbb3c 100755
--- a/mkroot/mkroot.sh
+++ b/mkroot/mkroot.sh
@@ -53,6 +53,7 @@ ${CROSS_COMPILE}cc --static -xc - -o /dev/null <<< "int main(void){return 0;}"||
# ----- Create hermetic build environment
+rm -rf generated
if [ -z "$NOAIRLOCK"] && [ -n "$CROSS_COMPILE" ]; then
# When cross compiling set host $PATH to binaries with known behavior by
# - building a host toybox later builds use as their command line
@@ -81,7 +82,7 @@ if [ -z "$NOLOGPATH" ]; then
CROSS_COMPILE=${CROSS_COMPILE##*/}
export WRAPDIR="$BUILD/record-commands" LOGPATH="$LOG"-commands.txt
rm -rf "$WRAPDIR" "$LOGPATH" generated/obj &&
- WRAPDIR="$WRAPDIR" CROSS_COMPILE= NOSTRIP=1 source mkroot/record-commands ||
+ eval "$(WRAPDIR="$WRAPDIR" CROSS_COMPILE= NOSTRIP=1 mkroot/record-commands)"||
exit 1
fi
@@ -134,7 +135,7 @@ if [ $$ -eq 1 ]; then
[ -z "$HANDOFF" ] && [ -e /mnt/init ] && HANDOFF=/mnt/init
[ -z "$HANDOFF" ] && HANDOFF=/bin/sh && echo -e '\e[?7hType exit when done.'
- setsid -c <>/dev/$(sed '$s@.*/@@' /sys/class/tty/console/active) >&0 2>&1 \
+ setsid -c <>/dev/$(sed '$s@.*[ /]@@' /sys/class/tty/console/active) >&0 2>&1 \
$HANDOFF
reboot -f &
sleep 5
@@ -152,7 +153,10 @@ root:x:0:0:root:/root:/bin/sh
guest:x:500:500:guest:/home/guest:/bin/sh
nobody:x:65534:65534:nobody:/proc/self:/dev/null
EOF
-echo -e 'root:x:0:\nguest:x:500:\nnobody:x:65534:' > "$ROOT"/etc/group || exit 1
+echo -e 'root:x:0:\nguest:x:500:\nnobody:x:65534:' > "$ROOT"/etc/group &&
+: ${VERSION:=$(toybox --version)} &&
+# Optional file, basically a comment
+echo $'NAME="mkroot"\nVERSION="'${VERSION#* }$'"\nHOME_URL="https://landley.net/toybox"' > "$ROOT"/etc/os-release || exit 1
# Build any packages listed on command line
for i in ${PKG:+plumbing $PKG}; do
@@ -177,6 +181,7 @@ fi
# Convert comma separated values in $1 to CONFIG=$2 lines
csv2cfg() { sed -E '/^$/d;s/([^,]*)($|,)/CONFIG_\1\n/g' <<< "$1" | sed '/^$/!{/=/!s/.*/&='"$2/}";}
+be2csv() { eval "echo $*" | tr ' ' ,; } # brace expansion to csv
# Set variables from $CROSS, die on unrecognized target:
# BUILTIN - if set, statically link initramfs into kernel image
@@ -191,12 +196,17 @@ get_target_config()
# Target-specific info in an (alphabetical order) if/else staircase
# Each target needs board config, serial console, RTC, ethernet, block device.
- if [ "$CROSS" == armv5l ]; then
+ KARGS=ttyS0 VMLINUX=vmlinux
+ if [ "$CROSS" == armv5l ] || [ "$CROSS" == armv4l ]; then
# This could use the same VIRT board as armv7, but let's demonstrate a
# different one requiring a separate device tree binary.
- QEMU="arm -M versatilepb -net nic,model=rtl8139 -net user"
KARCH=arm KARGS=ttyAMA0 VMLINUX=arch/arm/boot/zImage
- KCONF=CPU_ARM926T,MMU,VFP,ARM_THUMB,AEABI,ARCH_VERSATILE,ATAGS,DEPRECATED_PARAM_STRUCT,ARM_ATAG_DTB_COMPAT,ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND,SERIAL_AMBA_PL011,SERIAL_AMBA_PL011_CONSOLE,RTC_CLASS,RTC_DRV_PL031,RTC_HCTOSYS,PCI,PCI_VERSATILE,BLK_DEV_SD,SCSI,SCSI_LOWLEVEL,SCSI_SYM53C8XX_2,SCSI_SYM53C8XX_MMIO,NET_VENDOR_REALTEK,8139CP,SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
+ QEMU="arm -M versatilepb -net nic,model=rtl8139 -net user"
+ KCONF="$(be2csv CPU_ARM926T MMU VFP ARM_THUMB AEABI ARCH_VERSATILE ATAGS \
+ DEPRECATED_PARAM_STRUCT BLK_DEV_SD NET_VENDOR_REALTEK 8139CP \
+ ARM_ATAG_DTB_COMPAT{,_CMDLINE_EXTEND} PCI{,_VERSATILE} \
+ SERIAL_AMBA_PL011{,_CONSOLE} RTC_{CLASS,DRV_PL031,HCTOSYS} \
+ SCSI{,_LOWLEVEL,_SYM53C8XX_{2,MMIO,DMA_ADDRESSING_MODE=0}})"
DTB=versatile-pb.dtb
elif [ "$CROSS" == armv7l ] || [ "$CROSS" == aarch64 ]; then
if [ "$CROSS" == aarch64 ]; then
@@ -206,9 +216,13 @@ get_target_config()
QEMU="arm -M virt" KARCH=arm VMLINUX=arch/arm/boot/zImage
fi
KARGS=ttyAMA0
- KCONF=MMU,ARCH_MULTI_V7,ARCH_VIRT,SOC_DRA7XX,ARCH_OMAP2PLUS_TYPICAL,ARCH_ALPINE,ARM_THUMB,VDSO,CPU_IDLE,ARM_CPUIDLE,KERNEL_MODE_NEON,SERIAL_AMBA_PL011,SERIAL_AMBA_PL011_CONSOLE,RTC_CLASS,RTC_HCTOSYS,RTC_DRV_PL031,VIRTIO_MENU,VIRTIO_NET,PCI,PCI_HOST_GENERIC,VIRTIO_BLK,VIRTIO_PCI,VIRTIO_MMIO,ATA,ATA_SFF,ATA_BMDMA,ATA_PIIX,PATA_PLATFORM,PATA_OF_PLATFORM,ATA_GENERIC,ARM_LPAE
+ KCONF="$(be2csv MMU SOC_DRA7XX VDSO CPU_IDLE KERNEL_MODE_NEON \
+ ARCH_{MULTI_V7,VIRT,OMAP2PLUS_TYPICAL,ALPINE} ARM_{THUMB,CPUIDLE,LPAE} \
+ ATA{,_SFF,_BMDMA,_PIIX,_GENERIC} VIRTIO_{MENU,NET,BLK,PCI,MMIO} \
+ SERIAL_AMBA_PL011{,_CONSOLE} RTC_{CLASS,HCTOSYS,DRV_PL031} \
+ PATA_{,OF_}PLATFORM PCI{,_HOST_GENERIC})"
elif [ "$CROSS" == hexagon ]; then
- QEMU="hexagon -M comet" KARGS=ttyS0 VMLINUX=vmlinux
+ QEMU="hexagon -M comet"
KARCH="hexagon LLVM_IAS=1" KCONF=SPI,SPI_BITBANG,IOMMU_SUPPORT
elif [ "$CROSS" == i486 ] || [ "$CROSS" == i686 ] ||
[ "$CROSS" == x86_64 ] || [ "$CROSS" == x32 ]; then
@@ -220,46 +234,76 @@ get_target_config()
QEMU=x86_64 KCONF=64BIT
[ "$CROSS" == x32 ] && KCONF=X86_X32
fi
- KARCH=x86 KARGS=ttyS0 VMLINUX=arch/x86/boot/bzImage
- KCONF=$KCONF,UNWINDER_FRAME_POINTER,PCI,BLK_DEV_SD,ATA,ATA_SFF,ATA_BMDMA,ATA_PIIX,NET_VENDOR_INTEL,E1000,SERIAL_8250,SERIAL_8250_CONSOLE,RTC_CLASS
+ KARCH=x86 VMLINUX=arch/x86/boot/bzImage
+ KCONF+=,"$(be2csv UNWINDER_FRAME_POINTER PCI BLK_DEV_SD NET_VENDOR_INTEL \
+ E1000 RTC_CLASS ATA{,_SFF,_BMDMA,_PIIX} SERIAL_8250{,_CONSOLE})"
elif [ "$CROSS" == m68k ]; then
- QEMU="m68k -M q800" KARCH=m68k KARGS=ttyS0 VMLINUX=vmlinux
- KCONF=MMU,M68040,M68KFPU_EMU,MAC,SCSI,SCSI_LOWLEVEL,BLK_DEV_SD,SCSI_MAC_ESP,MACINTOSH_DRIVERS,NET_VENDOR_NATSEMI,MACSONIC,SERIAL_PMACZILOG,SERIAL_PMACZILOG_TTYS,SERIAL_PMACZILOG_CONSOLE
- elif [ "$CROSS" == mips ] || [ "$CROSS" == mipsel ]; then
- QEMU="mips -M malta" KARCH=mips KARGS=ttyS0 VMLINUX=vmlinux
- KCONF=MIPS_MALTA,CPU_MIPS32_R2,SERIAL_8250,SERIAL_8250_CONSOLE,PCI,BLK_DEV_SD,ATA,ATA_SFF,ATA_BMDMA,ATA_PIIX,NET_VENDOR_AMD,PCNET32,POWER_RESET,POWER_RESET_SYSCON
- [ "$CROSS" == mipsel ] && KCONF=$KCONF,CPU_LITTLE_ENDIAN &&
- QEMU="mipsel -M malta"
+ QEMU="m68k -M q800" KARCH=m68k
+ KCONF="$(be2csv MMU M68040 M68KFPU_EMU MAC BLK_DEV_SD MACINTOSH_DRIVERS \
+ NET_VENDOR_NATSEMI MACSONIC SCSI{,_LOWLEVEL,_MAC_ESP} \
+ SERIAL_PMACZILOG{,_TTYS,_CONSOLE})"
+ elif [ "$CROSS" == microblaze ]; then
+ QEMU="microblaze -M petalogix-s3adsp1800" KARCH=microblaze KARGS=ttyUL0
+ KCONF="$(be2csv MMU CPU_BIG_ENDIAN SERIAL_UARTLITE{,_CONSOLE} \
+ XILINX_{EMACLITE,MICROBLAZE0_{FAMILY="spartan3adsp",USE_{{MSR,PCMP}_INSTR,BARREL,HW_MUL}=1}})"
+ elif [ "${CROSS#mips}" != "$CROSS" ]; then # mips mipsel mips64 mips64el
+ QEMU="$CROSS -M malta" KARCH=mips
+ KCONF="$(be2csv MIPS_MALTA CPU_MIPS32_R2 BLK_DEV_SD NET_VENDOR_AMD PCNET32 \
+ PCI SERIAL_8250{,_CONSOLE} ATA{,_SFF,_BMDMA,_PIIX} POWER_RESET{,_SYSCON})"
+ [ "${CROSS/64/}" == "$CROSS" ] && KCONF+=,CPU_MIPS32_R2 ||
+ KCONF+=,64BIT,CPU_MIPS64_R1,MIPS32_O32
+ [ "${CROSS%el}" != "$CROSS" ] && KCONF+=,CPU_LITTLE_ENDIAN
elif [ "$CROSS" == or1k ]; then
- KARCH=openrisc QEMU="or1k -M or1k-sim" KARGS=FIXME VMLINUX=vmlinux BUILTIN=1
- KCONF=OPENRISC_BUILTIN_DTB=\"or1ksim\",ETHOC,SERIO,SERIAL_8250,SERIAL_8250_CONSOLE,SERIAL_OF_PLATFORM
+ KARCH=openrisc QEMU="or1k -M or1k-sim" KARGS=FIXME BUILTIN=1
+ KCONF="$(be2csv ETHOC SERIO SERIAL_OF_PLATFORM SERIAL_8250{,_CONSOLE})"
+ KCONF+=,OPENRISC_BUILTIN_DTB=\"or1ksim\"
elif [ "$CROSS" == powerpc ]; then
- KARCH=powerpc QEMU="ppc -M g3beige" KARGS=ttyS0 VMLINUX=vmlinux
- KCONF=ALTIVEC,PPC_PMAC,PPC_OF_BOOT_TRAMPOLINE,ATA,ATA_SFF,ATA_BMDMA,PATA_MACIO,BLK_DEV_SD,MACINTOSH_DRIVERS,ADB,ADB_CUDA,NET_VENDOR_NATSEMI,NET_VENDOR_8390,NE2K_PCI,SERIO,SERIAL_PMACZILOG,SERIAL_PMACZILOG_TTYS,SERIAL_PMACZILOG_CONSOLE,BOOTX_TEXT
+ KARCH=powerpc QEMU="ppc -M g3beige"
+ KCONF="$(be2csv ALTIVEC PATA_MACIO BLK_DEV_SD MACINTOSH_DRIVERS SERIO \
+ NET_VENDOR_{8390,NATSEMI} NE2K_PCI SERIAL_PMACZILOG{,_TTYS,_CONSOLE} \
+ ATA{,_SFF,_BMDMA} ADB{,_CUDA} BOOTX_TEXT PPC_{PMAC,OF_BOOT_TRAMPOLINE})"
elif [ "$CROSS" == powerpc64 ] || [ "$CROSS" == powerpc64le ]; then
KARCH=powerpc QEMU="ppc64 -M pseries -vga none" KARGS=hvc0
- VMLINUX=vmlinux
- KCONF=PPC64,PPC_PSERIES,PPC_OF_BOOT_TRAMPOLINE,BLK_DEV_SD,SCSI_LOWLEVEL,SCSI_IBMVSCSI,ATA,NET_VENDOR_IBM,IBMVETH,HVC_CONSOLE,PPC_TRANSACTIONAL_MEM,PPC_DISABLE_WERROR,SECTION_MISMATCH_WARN_ONLY
+ KCONF="$(be2csv PPC64 BLK_DEV_SD ATA NET_VENDOR_IBM IBMVETH HVC_CONSOLE \
+ PPC_{PSERIES,OF_BOOT_TRAMPOLINE,TRANSACTIONAL_MEM,DISABLE_WERROR} \
+ SCSI_{LOWLEVEL,IBMVSCSI})"
[ "$CROSS" == powerpc64le ] && KCONF=$KCONF,CPU_LITTLE_ENDIAN
elif [ "$CROSS" = s390x ]; then
QEMU="s390x" KARCH=s390 VMLINUX=arch/s390/boot/bzImage
- KCONF=MARCH_Z900,PACK_STACK,VIRTIO_NET,VIRTIO_BLK,SCLP_TTY,SCLP_CONSOLE,SCLP_VT220_TTY,SCLP_VT220_CONSOLE,S390_GUEST
+ KCONF="$(be2csv MARCH_Z900 PACK_STACK S390_GUEST VIRTIO_{NET,BLK} \
+ SCLP_VT220_{TTY,CONSOLE})"
elif [ "$CROSS" == sh2eb ]; then
- BUILTIN=1 KARCH=sh VMLINUX=vmlinux
- KCONF=CPU_SUBTYPE_J2,CPU_BIG_ENDIAN,SH_JCORE_SOC,SMP,BINFMT_ELF_FDPIC,JCORE_EMAC,SERIAL_UARTLITE,SERIAL_UARTLITE_CONSOLE,HZ_100,CMDLINE_OVERWRITE,SPI,SPI_JCORE,MMC,PWRSEQ_SIMPLE,MMC_BLOCK,MMC_SPI,BINMT_FLAT,BINFMT_MISC,DNOTIFY,INOTIFY_USER,FUSE_FS,I2C,I2C_HELPER_AUTO,LOCALVERSION_AUTO,MTD,MTD_SPI_NOR,MTD_SST25L,MTD_OF_PARTS,POSIX_MQUEUE,SYSVIPC,UEVENT_HELPER,UIO,UIO_PDRV_GENIRQ,FLATMEM_MANUAL,MEMORY_START=0x10000000,CMDLINE=\"console=ttyUL0\ earlycon\"
- KCONF+=,BFP_SYSCALL,CRYPTO_DES,CRYPTO_DH,CRYPTO_ECHAINIV,CRYPTO_LZO,CRYPTO_MANAGER_DISABLE_TESTS,CRYPTO_RSA,CRYPTO_SHA1,CRYPTO_SHA3,INET_DIAG,SERIAL_8250
- # TODO NET_9P,9P_FS fails to boot in 6.3, unaligned access?
- elif [ "$CROSS" == sh4 ]; then
- QEMU="sh4 -M r2d -serial null -serial mon:stdio" KARCH=sh
+ BUILTIN=1 KARCH=sh
+ KCONF="$(be2csv CPU_{SUBTYPE_J2,BIG_ENDIAN} SH_JCORE_SOC SMP JCORE_EMAC \
+ FLATMEM_MANUAL MEMORY_START=0x10000000 CMDLINE_OVERWRITE DNOTIFY FUSE_FS \
+ INOTIFY_USER SPI{,_JCORE} SERIAL_UARTLITE{,_CONSOLE} PWRSEQ_SIMPLE \
+ MMC{,_BLOCK,_SPI} UIO{,_PDRV_GENIRQ} MTD{,_SPI_NOR,_SST25L,_OF_PARTS} \
+ BINFMT_{ELF_FDPIC,MISC} I2C{,_HELPER_AUTO})"
+ KCONF+=,CMDLINE=\"console=ttyUL0\ earlycon\"
+ elif [ "$CROSS" == sh4 ] || [ "$CROSS" == sh4eb ]; then
+ QEMU="$CROSS -M r2d -serial null -serial mon:stdio" KARCH=sh
KARGS="ttySC1 noiotrap" VMLINUX=arch/sh/boot/zImage
- KCONF=CPU_SUBTYPE_SH7751R,MMU,VSYSCALL,SH_FPU,SH_RTS7751R2D,RTS7751R2D_PLUS,SERIAL_SH_SCI,SERIAL_SH_SCI_CONSOLE,PCI,NET_VENDOR_REALTEK,8139CP,PCI,BLK_DEV_SD,ATA,ATA_SFF,ATA_BMDMA,PATA_PLATFORM,BINFMT_ELF_FDPIC,BINFMT_FLAT,MEMORY_START=0x0c000000
-#see also SPI SPI_SH_SCI MFD_SM501 RTC_CLASS RTC_DRV_R9701 RTC_DRV_SH RTC_HCTOSYS
+ KCONF="$(be2csv CPU_SUBTYPE_SH7751R MMU VSYSCALL SH_{FPU,RTS7751R2D} PCI \
+ RTS7751R2D_PLUS SERIAL_SH_SCI{,_CONSOLE} NET_VENDOR_REALTEK 8139CP \
+ BLK_DEV_SD ATA{,_SFF,_BMDMA} PATA_PLATFORM BINFMT_ELF_FDPIC \
+ MEMORY_START=0x0c000000)"
+#see also SPI{,_SH_SCI} MFD_SM501 RTC_{CLASS,DRV_{R9701,SH},HCTOSYS}
+ [ "$CROSS" == sh4eb ] && KCONF+=,CPU_BIG_ENDIAN
else die "Unknown \$CROSS=$CROSS"
fi
}
+# Linux kernel .config symbols common to all architectures
+: ${GENERIC_KCONF:=$(be2csv PANIC_TIMEOUT=1 NO_HZ HIGH_RES_TIMERS RD_GZIP \
+ BINFMT_{ELF,SCRIPT} BLK_DEV{,_INITRD,_LOOP} EXT4_{FS,USE_FOR_EXT2} \
+ VFAT_FS FAT_DEFAULT_UTF8 MISC_FILESYSTEMS NLS_{CODEPAGE_437,ISO8859_1} \
+ SQUASHFS{,_XATTR,_ZLIB} TMPFS{,_POSIX_ACL} DEVTMPFS{,_MOUNT} \
+ NET{,DEVICES,_CORE,CONSOLE} PACKET UNIX INET IPV6 ETHERNET \
+ COMPAT_32BIT_TIME EARLY_PRINTK IKCONFIG{,_PROC})}
+
# ----- Build kernel for target
+INITRAMFS=initramfs.cpio.gz
if [ -z "$LINUX" ] || [ ! -d "$LINUX/kernel" ]; then
echo 'No $LINUX directory, kernel build skipped.'
else
@@ -270,7 +314,7 @@ else
# Write the qemu launch script
if [ -n "$QEMU" ]; then
- [ -z "$BUILTIN" ] && INITRD='-initrd "$DIR"/initramfs.cpio.gz'
+ [ -z "$BUILTIN" ] && INITRD='-initrd "$DIR"/'"$INITRAMFS"
{ echo DIR='"$(dirname $0)";' qemu-system-"$QEMU" -m 256 '"$@"' $QEMU_MORE \
-nographic -no-reboot -kernel '"$DIR"'/linux-kernel $INITRD \
${DTB:+-dtb '"$DIR"'/linux.dtb} \
@@ -284,30 +328,28 @@ else
pushd "$LINUX" && make distclean && popd &&
cp -sfR "$LINUX" "$TEMP/linux" && pushd "$TEMP/linux" &&
- # Write linux-miniconfig
+ # Write microconfig (minimal symbol name/value list in CSV format)
mkdir -p "$OUTDOC" &&
- { echo "# make ARCH=$KARCH allnoconfig KCONFIG_ALLCONFIG=linux-miniconfig"
- echo -e "# make ARCH=$KARCH -j \$(nproc)\n# boot $VMLINUX\n\n"
-
- # Expand list of =y symbols, first generic then architecture-specific
- for i in BINFMT_ELF,BINFMT_SCRIPT,PANIC_TIMEOUT=1,NO_HZ,HIGH_RES_TIMERS,BLK_DEV,BLK_DEV_INITRD,RD_GZIP,BLK_DEV_LOOP,EXT4_FS,EXT4_USE_FOR_EXT2,VFAT_FS,FAT_DEFAULT_UTF8,NLS_CODEPAGE_437,NLS_ISO8859_1,MISC_FILESYSTEMS,SQUASHFS,SQUASHFS_XATTR,SQUASHFS_ZLIB,DEVTMPFS,DEVTMPFS_MOUNT,TMPFS,TMPFS_POSIX_ACL,NET,PACKET,UNIX,INET,IPV6,NETDEVICES,NET_CORE,NETCONSOLE,ETHERNET,COMPAT_32BIT_TIME,EARLY_PRINTK,IKCONFIG,IKCONFIG_PROC "$KCONF" ${MODULES+MODULES,MODULE_UNLOAD} "$KEXTRA" ; do
- echo "$i" >> "$OUTDOC"/linux-microconfig
+ for i in "$GENERIC_KCONF" "$KCONF" ${MODULES+MODULES,MODULE_UNLOAD} "$KEXTRA"
+ do echo "$i"; done > "$OUTDOC"/linux-microconfig &&
+
+ # expand to miniconfig (symbol list to switch on after running "allnoconfig")
+ {
+ echo "# make ARCH=$KARCH allnoconfig KCONFIG_ALLCONFIG=linux-miniconfig"
+ echo "# make ARCH=$KARCH -j \$(nproc)"
+ echo "# boot $VMLINUX${DTB:+ dtb $DTB} console=$KARGS"
+ echo
+ while read i; do
echo "# architecture ${X:-independent}"
csv2cfg "$i" y
X=${X:+extra} X=${X:-specific}
- done
+ done < "$OUTDOC"/linux-microconfig
[ -n "$BUILTIN" ] && echo -e CONFIG_INITRAMFS_SOURCE="\"$OUTPUT/fs\""
for i in $MODULES; do csv2cfg "$i" m; done
- echo "$KERNEL_CONFIG"
} > "$OUTDOC/linux-miniconfig" &&
- make ARCH=$KARCH allnoconfig KCONFIG_ALLCONFIG="$OUTDOC/linux-miniconfig" &&
- # Second config pass to remove stupid kernel defaults
- # See http://lkml.iu.edu/hypermail/linux/kernel/1912.3/03493.html
- sed -e 's/# CONFIG_EXPERT .*/CONFIG_EXPERT=y/' -e "$(sed -E -e '/^$/d' \
- -e 's@([^,]*)($|,)@/^CONFIG_\1=y/d;$a# CONFIG_\1 is not set\n@g' \
- <<< VT,SCHED_DEBUG,DEBUG_MISC,X86_DEBUG_FPU)" -i .config &&
- yes "" | make ARCH=$KARCH oldconfig > /dev/null &&
+ # Expand miniconfig to full .config
+ make ARCH=$KARCH allnoconfig KCONFIG_ALLCONFIG="$OUTDOC/linux-miniconfig" &&
cp .config "$OUTDOC/linux-fullconfig" &&
# Build kernel. Copy config, device tree binary, and kernel binary to output
@@ -322,12 +364,11 @@ else
fi
# clean up and package root filesystem for initramfs.
-if [ -z "$BUILTIN" ]; then
- announce initramfs
- { (cd "$ROOT" && find . -printf '%P\n' | cpio -o -H newc -R +0:+0 ) || exit 1
- ! test -e "$OUTDOC/modules.cpio.gz" || zcat $_;} | gzip \
- > "$OUTPUT"/initramfs.cpio.gz || exit 1
-fi
+announce initramfs
+[ -z "$BUILTIN" ] && DIR="$OUTPUT" || DIR="$OUTDOC"
+{ (cd "$ROOT" && find . -printf '%P\n' | cpio -o -H newc -R +0:+0 ) || exit 1
+ ! test -e "$OUTDOC/modules.cpio.gz" || zcat $_;} | gzip \
+ > "$DIR/$INITRAMFS" || exit 1
mv "$LOG".{n,y} && echo "Output is in $OUTPUT"
rmdir "$TEMP" 2>/dev/null || exit 0 # remove if empty, not an error
diff --git a/mkroot/packages/tests b/mkroot/packages/tests
index bca3b40c..5e27f4a1 100755
--- a/mkroot/packages/tests
+++ b/mkroot/packages/tests
@@ -10,6 +10,5 @@ download 6694284723e034f0c564e81a30879939d5ef8b7e \
cp "$DOWNLOAD"/{usb,pci}.ids "$ROOT/etc/" || exit 1
-# Enable module support in the kernel and add a couple test modules
-KEXTRA=MODULES,MODULE_UNLOAD,"$KEXTRA"
+# add a couple test modules
MODULES+=FSCACHE,CACHEFILES
diff --git a/mkroot/record-commands b/mkroot/record-commands
index 6e63c5b7..71f2c4ef 100755
--- a/mkroot/record-commands
+++ b/mkroot/record-commands
@@ -5,38 +5,31 @@
[ -z "$WRAPDIR" ] && WRAPDIR="$PWD"/record-commands && RM=$(which rm)
[ -z "$LOGPATH" ] && export LOGPATH="$PWD"/log.txt
-if [ ${#BASH_SOURCE[@]} -lt 2 ] && [ $# -eq 0 ]
-then
- echo "usage: WRAPDIR=dir LOGPATH=log.txt record-commands COMMAND..."
- echo 'Then examine log.txt. "record-commands echo" to just setup $WRAPDIR'
- exit 1
-fi
-
if [ ! -x "$WRAPDIR/logpath" ]
then
+ LOG="$(which logpath)"
mkdir -p "$WRAPDIR" || exit 1
- [ -e "$(which logpath)" ] && cp -H "$(which logpath)" "$WRAPDIR/logpath" ||
- mkdir -p "$WRAPDIR" && PREFIX="$WRAPDIR/" scripts/single.sh logpath ||
- exit 1
- find $(tr : '\n' <<< "$PATH") -type f,l -maxdepth 1 -executable \
- -exec basename {} \; | while read FILE
- do
- ln -s logpath "$WRAPDIR/$FILE" 2>/dev/null
- done
+ [ -e "$LOG" ] && cp -H "$LOG" "$WRAPDIR/logpath" || { cd "$(dirname $0)/.." &&
+ PREFIX="$WRAPDIR/" scripts/single.sh logpath >/dev/null &&
+ LOG="$PWD/logpath" || exit 1; }
+ tr : '\n' <<< "$PATH" | while read i; do
+ find "$i" \( -type f -o -type l \) -maxdepth 1 -executable -exec basename {} \; | \
+ while read FILE; do ln -s logpath "$WRAPDIR/$FILE" 2>/dev/null; done
+ done
fi
# Delete old log (if any)
rm -f "$LOGPATH"
# When sourced, set up wrapper for current context.
-export PATH="$WRAPDIR:$PATH"
-if [ ${#BASH_SOURCE[@]} -lt 2 ]
+if [ $# -gt 0 ]
then
- "$@"
+ PATH="$WRAPDIR:$PATH" "$@"
X=$?
-
- [ ! -z "$RM" ] && "$RM" -rf "$WRAPDIR"
+ [ -n "$RM" ] && "$RM" -rf "$WRAPDIR"
exit $X
+else
+ echo export LOGPATH=${LOGPATH@Q} PATH=${WRAPDIR@Q}:${PATH@Q}
fi
diff --git a/mkroot/tar-for-web.sh b/mkroot/tar-for-web.sh
index c31b2888..5bb6d80c 100755
--- a/mkroot/tar-for-web.sh
+++ b/mkroot/tar-for-web.sh
@@ -25,11 +25,11 @@ Bootable system images created by:
mkroot/mkroot.sh LINUX=~/linux CROSS=allnonstop
Each system image is built from two packages: toybox and linux.
-Run the ./qemu-*.sh script in each tarball to boot the system
-to a shell prompt under qemu. Run the "exit" command to shut down the
-virtual system and exit the emulator.
+The run-qemu.sh script in each tarball should boot the system
+to a shell prompt under qemu, exit from that shell to shut down the
+virtual system and stop the emulator.
-See https://landley.net/toybox/FAQ.html#mkroot for details.
+See https://landley.net/toybox/faq.html#mkroot for details.
Built from mkroot $(git describe --tags), and Linux $KVERS with patches in linux-patches/
EOF
diff --git a/scripts/make.sh b/scripts/make.sh
index 5fef9887..512fdc75 100755
--- a/scripts/make.sh
+++ b/scripts/make.sh
@@ -147,9 +147,9 @@ fi
# Rebuild config.h from .config
$SED -En $KCONFIG_CONFIG > "$GENDIR"/config.h \
- -e 's/^# CONFIG_(.*) is not set.*/#define CFG_\1 0\n#define USE_\1(...)/p' \
- -e 's/^CONFIG_(.*)=y.*/#define CFG_\1 1\n#define USE_\1(...) __VA_ARGS__/p'\
- || exit 1
+ -e 's/^# CONFIG_(.*) is not set.*/#define CFG_\1 0\n#define USE_\1(...)/p;t' \
+ -e 's/^CONFIG_(.*)=y.*/#define CFG_\1 1\n#define USE_\1(...) __VA_ARGS__/p;t'\
+ -e 's/^CONFIG_(.*)=/#define CFG_\1 /p' || exit 1
# Process config.h and newtoys.h to generate FLAG_x macros. Note we must
# always #define the relevant macro, even when it's disabled, because we
diff --git a/scripts/mcm-buildall.sh b/scripts/mcm-buildall.sh
index b5b19e5e..a27b9c07 100755
--- a/scripts/mcm-buildall.sh
+++ b/scripts/mcm-buildall.sh
@@ -29,7 +29,8 @@ TARGETS=(i686:: aarch64:eabi:
"armv7m:eabi:--with-arch=armv7-m --with-mode=thumb --disable-libatomic --enable-default-pie"
armv7r:eabihf:"--with-arch=armv7-r --enable-default-pie"
i486:: m68k:: microblaze:: mips:: mips64:: mipsel:: or1k:: powerpc::
- powerpc64:: powerpc64le:: riscv64:: s390x:: sh2eb:fdpic:--with-cpu=mj2
+ powerpc64:: powerpc64le:: riscv32:: riscv64:: s390x::
+ sh2eb:fdpic:--with-cpu=mj2
sh4::--enable-incomplete-targets sh4eb::--enable-incomplete-targets
x86_64::--with-mtune=nocona x86_64@x32:x32:
)
@@ -173,13 +174,13 @@ patch_mcm()
# and doesn't even use the latest musl release by default, so fix it up.
# Select newer package versions and don't use dodgy mirrors
- sed -i 's/mirror//;s/\(LINUX_VER =\).*/\1 6.6/;s/\(GCC_VER =\).*/\1 11.2.0/' \
+ sed -i 's/mirror//;s/\(LINUX_VER =\).*/\1 6.8/;s/\(GCC_VER =\).*/\1 11.2.0/' \
Makefile &&
- echo 'c8dbfa8285f1a90596a227690653d84b9eb2debe linux-6.6.tar.xz' > \
- hashes/linux-6.6.tar.xz.sha1 &&
+ echo 'c9ab5b95c0b8e9e41290d3fc53b4e5cb2e8abb75 linux-6.8.tar.xz' > \
+ hashes/linux-6.8.tar.xz.sha1 &&
# mcm redundantly downloads tarball if hash file has newer timestamp,
# and it whack-a-moles how to download kernels by version for some reason.
- touch -d @1 hashes/linux-6.6.tar.xz.sha1 &&
+ touch -d @1 hashes/linux-6.8.tar.xz.sha1 &&
sed -i 's/\(.*linux-\)3\(.*\)v3.x/\16\2v6.x/' Makefile &&
# nommu toolchains need to vfork()+pipe, and or1k has different kernel arch
diff --git a/scripts/prereq/build.sh b/scripts/prereq/build.sh
new file mode 100755
index 00000000..ac1fa11b
--- /dev/null
+++ b/scripts/prereq/build.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+BUILD='cc -funsigned-char -I scripts/prereq -I . -Os -ffunction-sections -fdata-sections -fno-asynchronous-unwind-tables -fno-strict-aliasing -DTOYBOX_VERSION=""'
+LINK=''
+FILES="
+main.c toys/lsb/gzip.c toys/other/readlink.c toys/other/which.c
+toys/pending/tr.c toys/posix/basename.c toys/posix/cat.c toys/posix/chmod.c
+toys/posix/cmp.c toys/posix/dirname.c toys/posix/echo.c toys/posix/fold.c
+toys/posix/grep.c toys/posix/head.c toys/posix/ln.c toys/posix/ls.c
+toys/posix/mkdir.c toys/posix/od.c toys/posix/rm.c toys/posix/sed.c
+toys/posix/sort.c toys/posix/tail.c toys/posix/tee.c toys/posix/uname.c
+toys/posix/wc.c toys/posix/xargs.c
+"
+
+$BUILD lib/*.c $FILES $LINK -o toybox-prereq
diff --git a/scripts/prereq/generated/config.h b/scripts/prereq/generated/config.h
new file mode 100644
index 00000000..60c87b5b
--- /dev/null
+++ b/scripts/prereq/generated/config.h
@@ -0,0 +1,706 @@
+#define CFG_TOYBOX_ON_ANDROID 0
+#define USE_TOYBOX_ON_ANDROID(...)
+#define CFG_TOYBOX_FORK 1
+#define USE_TOYBOX_FORK(...) __VA_ARGS__
+#define CFG_BASENAME 1
+#define USE_BASENAME(...) __VA_ARGS__
+#define CFG_CAL 0
+#define USE_CAL(...)
+#define CFG_CAT 1
+#define USE_CAT(...) __VA_ARGS__
+#define CFG_CHGRP 0
+#define USE_CHGRP(...)
+#define CFG_CHOWN 0
+#define USE_CHOWN(...)
+#define CFG_CHMOD 1
+#define USE_CHMOD(...) __VA_ARGS__
+#define CFG_CKSUM 0
+#define USE_CKSUM(...)
+#define CFG_CRC32 0
+#define USE_CRC32(...)
+#define CFG_CMP 1
+#define USE_CMP(...) __VA_ARGS__
+#define CFG_COMM 0
+#define USE_COMM(...)
+#define CFG_CP 0
+#define USE_CP(...)
+#define CFG_MV 0
+#define USE_MV(...)
+#define CFG_INSTALL 0
+#define USE_INSTALL(...)
+#define CFG_CPIO 0
+#define USE_CPIO(...)
+#define CFG_CUT 0
+#define USE_CUT(...)
+#define CFG_DATE 0
+#define USE_DATE(...)
+#define CFG_DD 0
+#define USE_DD(...)
+#define CFG_DF 0
+#define USE_DF(...)
+#define CFG_DIRNAME 1
+#define USE_DIRNAME(...) __VA_ARGS__
+#define CFG_DU 0
+#define USE_DU(...)
+#define CFG_ECHO 1
+#define USE_ECHO(...) __VA_ARGS__
+#define CFG_ENV 0
+#define USE_ENV(...)
+#define CFG_EXPAND 0
+#define USE_EXPAND(...)
+#define CFG_FALSE 0
+#define USE_FALSE(...)
+#define CFG_FILE 0
+#define USE_FILE(...)
+#define CFG_FIND 0
+#define USE_FIND(...)
+#define CFG_FOLD 1
+#define USE_FOLD(...) __VA_ARGS__
+#define CFG_GETCONF 0
+#define USE_GETCONF(...)
+#define CFG_GREP 1
+#define USE_GREP(...) __VA_ARGS__
+#define CFG_EGREP 1
+#define USE_EGREP(...) __VA_ARGS__
+#define CFG_FGREP 1
+#define USE_FGREP(...) __VA_ARGS__
+#define CFG_HEAD 1
+#define USE_HEAD(...) __VA_ARGS__
+#define CFG_ICONV 0
+#define USE_ICONV(...)
+#define CFG_ID 0
+#define USE_ID(...)
+#define CFG_ID_Z 0
+#define USE_ID_Z(...)
+#define CFG_GROUPS 0
+#define USE_GROUPS(...)
+#define CFG_LOGNAME 0
+#define USE_LOGNAME(...)
+#define CFG_WHOAMI 0
+#define USE_WHOAMI(...)
+#define CFG_KILL 0
+#define USE_KILL(...)
+#define CFG_KILLALL5 0
+#define USE_KILLALL5(...)
+#define CFG_LINK 0
+#define USE_LINK(...)
+#define CFG_LN 1
+#define USE_LN(...) __VA_ARGS__
+#define CFG_LOGGER 0
+#define USE_LOGGER(...)
+#define CFG_LS 1
+#define USE_LS(...) __VA_ARGS__
+#define CFG_MKDIR 1
+#define USE_MKDIR(...) __VA_ARGS__
+#define CFG_MKDIR_Z 0
+#define USE_MKDIR_Z(...)
+#define CFG_MKFIFO 0
+#define USE_MKFIFO(...)
+#define CFG_MKFIFO_Z 0
+#define USE_MKFIFO_Z(...)
+#define CFG_NICE 0
+#define USE_NICE(...)
+#define CFG_NL 0
+#define USE_NL(...)
+#define CFG_NOHUP 0
+#define USE_NOHUP(...)
+#define CFG_OD 1
+#define USE_OD(...) __VA_ARGS__
+#define CFG_PASTE 0
+#define USE_PASTE(...)
+#define CFG_PATCH 0
+#define USE_PATCH(...)
+#define CFG_PRINTF 0
+#define USE_PRINTF(...)
+#define CFG_PS 0
+#define USE_PS(...)
+#define CFG_TOP 0
+#define USE_TOP(...)
+#define CFG_IOTOP 0
+#define USE_IOTOP(...)
+#define CFG_PGREP 0
+#define USE_PGREP(...)
+#define CFG_PKILL 0
+#define USE_PKILL(...)
+#define CFG_PWD 0
+#define USE_PWD(...)
+#define CFG_RENICE 0
+#define USE_RENICE(...)
+#define CFG_RM 1
+#define USE_RM(...) __VA_ARGS__
+#define CFG_RMDIR 0
+#define USE_RMDIR(...)
+#define CFG_SED 1
+#define USE_SED(...) __VA_ARGS__
+#define CFG_SLEEP 0
+#define USE_SLEEP(...)
+#define CFG_SORT 1
+#define USE_SORT(...) __VA_ARGS__
+#define CFG_SORT_FLOAT 0
+#define USE_SORT_FLOAT(...)
+#define CFG_SPLIT 0
+#define USE_SPLIT(...)
+#define CFG_STRINGS 0
+#define USE_STRINGS(...)
+#define CFG_TAIL 1
+#define USE_TAIL(...) __VA_ARGS__
+#define CFG_TAR 0
+#define USE_TAR(...)
+#define CFG_TEE 1
+#define USE_TEE(...) __VA_ARGS__
+#define CFG_TEST 0
+#define USE_TEST(...)
+#define CFG_TEST_GLUE 0
+#define USE_TEST_GLUE(...)
+#define CFG_TIME 0
+#define USE_TIME(...)
+#define CFG_TOUCH 0
+#define USE_TOUCH(...)
+#define CFG_TRUE 0
+#define USE_TRUE(...)
+#define CFG_TSORT 0
+#define USE_TSORT(...)
+#define CFG_TTY 0
+#define USE_TTY(...)
+#define CFG_ULIMIT 0
+#define USE_ULIMIT(...)
+#define CFG_ARCH 0
+#define USE_ARCH(...)
+#define CFG_UNAME 1
+#define USE_UNAME(...) __VA_ARGS__
+#define CFG_UNIQ 0
+#define USE_UNIQ(...)
+#define CFG_UNLINK 0
+#define USE_UNLINK(...)
+#define CFG_UUDECODE 0
+#define USE_UUDECODE(...)
+#define CFG_UUENCODE 0
+#define USE_UUENCODE(...)
+#define CFG_WC 1
+#define USE_WC(...) __VA_ARGS__
+#define CFG_WHO 0
+#define USE_WHO(...)
+#define CFG_XARGS 1
+#define USE_XARGS(...) __VA_ARGS__
+#define CFG_ARP 0
+#define USE_ARP(...)
+#define CFG_ARPING 0
+#define USE_ARPING(...)
+#define CFG_BC 0
+#define USE_BC(...)
+#define CFG_BOOTCHARTD 0
+#define USE_BOOTCHARTD(...)
+#define CFG_BRCTL 0
+#define USE_BRCTL(...)
+#define CFG_CHSH 0
+#define USE_CHSH(...)
+#define CFG_CROND 0
+#define USE_CROND(...)
+#define CFG_CRONTAB 0
+#define USE_CRONTAB(...)
+#define CFG_CSPLIT 0
+#define USE_CSPLIT(...)
+#define CFG_DHCP 0
+#define USE_DHCP(...)
+#define CFG_DHCP6 0
+#define USE_DHCP6(...)
+#define CFG_DHCPD 0
+#define USE_DHCPD(...)
+#define CFG_DEBUG_DHCP 0
+#define USE_DEBUG_DHCP(...)
+#define CFG_DIFF 0
+#define USE_DIFF(...)
+#define CFG_DUMPLEASES 0
+#define USE_DUMPLEASES(...)
+#define CFG_EXPR 0
+#define USE_EXPR(...)
+#define CFG_FDISK 0
+#define USE_FDISK(...)
+#define CFG_FSCK 0
+#define USE_FSCK(...)
+#define CFG_GETFATTR 0
+#define USE_GETFATTR(...)
+#define CFG_GETTY 0
+#define USE_GETTY(...)
+#define CFG_GITCOMPAT 0
+#define USE_GITCOMPAT(...)
+#define CFG_GITCLONE 0
+#define USE_GITCLONE(...)
+#define CFG_GITINIT 0
+#define USE_GITINIT(...)
+#define CFG_GITREMOTE 0
+#define USE_GITREMOTE(...)
+#define CFG_GITFETCH 0
+#define USE_GITFETCH(...)
+#define CFG_GITCHECKOUT 0
+#define USE_GITCHECKOUT(...)
+#define CFG_GROUPADD 0
+#define USE_GROUPADD(...)
+#define CFG_GROUPDEL 0
+#define USE_GROUPDEL(...)
+#define CFG_HEXDUMP 0
+#define USE_HEXDUMP(...)
+#define CFG_HD 0
+#define USE_HD(...)
+#define CFG_INIT 0
+#define USE_INIT(...)
+#define CFG_IP 0
+#define USE_IP(...)
+#define CFG_IPCRM 0
+#define USE_IPCRM(...)
+#define CFG_IPCS 0
+#define USE_IPCS(...)
+#define CFG_KLOGD 0
+#define USE_KLOGD(...)
+#define CFG_KLOGD_SOURCE_RING_BUFFER 0
+#define USE_KLOGD_SOURCE_RING_BUFFER(...)
+#define CFG_LAST 0
+#define USE_LAST(...)
+#define CFG_LSOF 0
+#define USE_LSOF(...)
+#define CFG_MAN 0
+#define USE_MAN(...)
+#define CFG_MDEV 0
+#define USE_MDEV(...)
+#define CFG_MDEV_CONF 0
+#define USE_MDEV_CONF(...)
+#define CFG_MKE2FS 0
+#define USE_MKE2FS(...)
+#define CFG_MKE2FS_JOURNAL 0
+#define USE_MKE2FS_JOURNAL(...)
+#define CFG_MKE2FS_GEN 0
+#define USE_MKE2FS_GEN(...)
+#define CFG_MKE2FS_LABEL 0
+#define USE_MKE2FS_LABEL(...)
+#define CFG_MKE2FS_EXTENDED 0
+#define USE_MKE2FS_EXTENDED(...)
+#define CFG_MODPROBE 0
+#define USE_MODPROBE(...)
+#define CFG_MORE 0
+#define USE_MORE(...)
+#define CFG_ROUTE 0
+#define USE_ROUTE(...)
+#define CFG_SH 0
+#define USE_SH(...)
+#define CFG_CD 0
+#define USE_CD(...)
+#define CFG_DECLARE 0
+#define USE_DECLARE(...)
+#define CFG_EXIT 0
+#define USE_EXIT(...)
+#define CFG_SET 0
+#define USE_SET(...)
+#define CFG_UNSET 0
+#define USE_UNSET(...)
+#define CFG_EVAL 0
+#define USE_EVAL(...)
+#define CFG_EXEC 0
+#define USE_EXEC(...)
+#define CFG_EXPORT 0
+#define USE_EXPORT(...)
+#define CFG_JOBS 0
+#define USE_JOBS(...)
+#define CFG_LOCAL 0
+#define USE_LOCAL(...)
+#define CFG_SHIFT 0
+#define USE_SHIFT(...)
+#define CFG_SOURCE 0
+#define USE_SOURCE(...)
+#define CFG_WAIT 0
+#define USE_WAIT(...)
+#define CFG_STRACE 0
+#define USE_STRACE(...)
+#define CFG_STTY 0
+#define USE_STTY(...)
+#define CFG_SULOGIN 0
+#define USE_SULOGIN(...)
+#define CFG_SYSLOGD 0
+#define USE_SYSLOGD(...)
+#define CFG_TCPSVD 0
+#define USE_TCPSVD(...)
+#define CFG_TELNET 0
+#define USE_TELNET(...)
+#define CFG_TELNETD 0
+#define USE_TELNETD(...)
+#define CFG_TFTP 0
+#define USE_TFTP(...)
+#define CFG_TFTPD 0
+#define USE_TFTPD(...)
+#define CFG_TR 1
+#define USE_TR(...) __VA_ARGS__
+#define CFG_TRACEROUTE 0
+#define USE_TRACEROUTE(...)
+#define CFG_USERADD 0
+#define USE_USERADD(...)
+#define CFG_USERDEL 0
+#define USE_USERDEL(...)
+#define CFG_VI 0
+#define USE_VI(...)
+#define CFG_XZCAT 0
+#define USE_XZCAT(...)
+#define CFG_ACPI 0
+#define USE_ACPI(...)
+#define CFG_ASCII 0
+#define USE_ASCII(...)
+#define CFG_UNICODE 0
+#define USE_UNICODE(...)
+#define CFG_BASE64 0
+#define USE_BASE64(...)
+#define CFG_BASE32 0
+#define USE_BASE32(...)
+#define CFG_BLKDISCARD 0
+#define USE_BLKDISCARD(...)
+#define CFG_BLKID 0
+#define USE_BLKID(...)
+#define CFG_FSTYPE 0
+#define USE_FSTYPE(...)
+#define CFG_BLOCKDEV 0
+#define USE_BLOCKDEV(...)
+#define CFG_BUNZIP2 0
+#define USE_BUNZIP2(...)
+#define CFG_BZCAT 0
+#define USE_BZCAT(...)
+#define CFG_CHCON 0
+#define USE_CHCON(...)
+#define CFG_CHROOT 0
+#define USE_CHROOT(...)
+#define CFG_CHRT 0
+#define USE_CHRT(...)
+#define CFG_CLEAR 0
+#define USE_CLEAR(...)
+#define CFG_COUNT 0
+#define USE_COUNT(...)
+#define CFG_DEVMEM 0
+#define USE_DEVMEM(...)
+#define CFG_DOS2UNIX 0
+#define USE_DOS2UNIX(...)
+#define CFG_UNIX2DOS 0
+#define USE_UNIX2DOS(...)
+#define CFG_EJECT 0
+#define USE_EJECT(...)
+#define CFG_FACTOR 0
+#define USE_FACTOR(...)
+#define CFG_FALLOCATE 0
+#define USE_FALLOCATE(...)
+#define CFG_FLOCK 0
+#define USE_FLOCK(...)
+#define CFG_FMT 0
+#define USE_FMT(...)
+#define CFG_FREE 0
+#define USE_FREE(...)
+#define CFG_FREERAMDISK 0
+#define USE_FREERAMDISK(...)
+#define CFG_FSFREEZE 0
+#define USE_FSFREEZE(...)
+#define CFG_FSYNC 0
+#define USE_FSYNC(...)
+#define CFG_GETOPT 0
+#define USE_GETOPT(...)
+#define CFG_GPIODETECT 0
+#define USE_GPIODETECT(...)
+#define CFG_GPIOFIND 0
+#define USE_GPIOFIND(...)
+#define CFG_GPIOINFO 0
+#define USE_GPIOINFO(...)
+#define CFG_GPIOGET 0
+#define USE_GPIOGET(...)
+#define CFG_GPIOSET 0
+#define USE_GPIOSET(...)
+#define CFG_HELP 0
+#define USE_HELP(...)
+#define CFG_HEXEDIT 0
+#define USE_HEXEDIT(...)
+#define CFG_HWCLOCK 0
+#define USE_HWCLOCK(...)
+#define CFG_I2CDETECT 0
+#define USE_I2CDETECT(...)
+#define CFG_I2CDUMP 0
+#define USE_I2CDUMP(...)
+#define CFG_I2CGET 0
+#define USE_I2CGET(...)
+#define CFG_I2CSET 0
+#define USE_I2CSET(...)
+#define CFG_I2CTRANSFER 0
+#define USE_I2CTRANSFER(...)
+#define CFG_INOTIFYD 0
+#define USE_INOTIFYD(...)
+#define CFG_INSMOD 0
+#define USE_INSMOD(...)
+#define CFG_IONICE 0
+#define USE_IONICE(...)
+#define CFG_IORENICE 0
+#define USE_IORENICE(...)
+#define CFG_LINUX32 0
+#define USE_LINUX32(...)
+#define CFG_LOGIN 0
+#define USE_LOGIN(...)
+#define CFG_LOSETUP 0
+#define USE_LOSETUP(...)
+#define CFG_LSATTR 0
+#define USE_LSATTR(...)
+#define CFG_CHATTR 0
+#define USE_CHATTR(...)
+#define CFG_LSMOD 0
+#define USE_LSMOD(...)
+#define CFG_LSPCI 0
+#define USE_LSPCI(...)
+#define CFG_LSUSB 0
+#define USE_LSUSB(...)
+#define CFG_MAKEDEVS 0
+#define USE_MAKEDEVS(...)
+#define CFG_MCOOKIE 0
+#define USE_MCOOKIE(...)
+#define CFG_MEMEATER 0
+#define USE_MEMEATER(...)
+#define CFG_MIX 0
+#define USE_MIX(...)
+#define CFG_MKPASSWD 0
+#define USE_MKPASSWD(...)
+#define CFG_MKSWAP 0
+#define USE_MKSWAP(...)
+#define CFG_MODINFO 0
+#define USE_MODINFO(...)
+#define CFG_MOUNTPOINT 0
+#define USE_MOUNTPOINT(...)
+#define CFG_NBD_CLIENT 0
+#define USE_NBD_CLIENT(...)
+#define CFG_NBD_SERVER 0
+#define USE_NBD_SERVER(...)
+#define CFG_UNSHARE 0
+#define USE_UNSHARE(...)
+#define CFG_NSENTER 0
+#define USE_NSENTER(...)
+#define CFG_ONEIT 0
+#define USE_ONEIT(...)
+#define CFG_OPENVT 0
+#define USE_OPENVT(...)
+#define CFG_CHVT 0
+#define USE_CHVT(...)
+#define CFG_DEALLOCVT 0
+#define USE_DEALLOCVT(...)
+#define CFG_PARTPROBE 0
+#define USE_PARTPROBE(...)
+#define CFG_PIVOT_ROOT 0
+#define USE_PIVOT_ROOT(...)
+#define CFG_PMAP 0
+#define USE_PMAP(...)
+#define CFG_PRINTENV 0
+#define USE_PRINTENV(...)
+#define CFG_PWDX 0
+#define USE_PWDX(...)
+#define CFG_PWGEN 0
+#define USE_PWGEN(...)
+#define CFG_READAHEAD 0
+#define USE_READAHEAD(...)
+#define CFG_READELF 0
+#define USE_READELF(...)
+#define CFG_READLINK 1
+#define USE_READLINK(...) __VA_ARGS__
+#define CFG_REALPATH 0
+#define USE_REALPATH(...)
+#define CFG_REBOOT 0
+#define USE_REBOOT(...)
+#define CFG_RESET 0
+#define USE_RESET(...)
+#define CFG_REV 0
+#define USE_REV(...)
+#define CFG_RMMOD 0
+#define USE_RMMOD(...)
+#define CFG_RTCWAKE 0
+#define USE_RTCWAKE(...)
+#define CFG_SETFATTR 0
+#define USE_SETFATTR(...)
+#define CFG_SETSID 0
+#define USE_SETSID(...)
+#define CFG_SHA3SUM 0
+#define USE_SHA3SUM(...)
+#define CFG_SHRED 0
+#define USE_SHRED(...)
+#define CFG_SHUF 0
+#define USE_SHUF(...)
+#define CFG_STAT 0
+#define USE_STAT(...)
+#define CFG_SWAPOFF 0
+#define USE_SWAPOFF(...)
+#define CFG_SWAPON 0
+#define USE_SWAPON(...)
+#define CFG_SWITCH_ROOT 0
+#define USE_SWITCH_ROOT(...)
+#define CFG_SYSCTL 0
+#define USE_SYSCTL(...)
+#define CFG_TAC 0
+#define USE_TAC(...)
+#define CFG_NPROC 0
+#define USE_NPROC(...)
+#define CFG_TASKSET 0
+#define USE_TASKSET(...)
+#define CFG_TIMEOUT 0
+#define USE_TIMEOUT(...)
+#define CFG_TRUNCATE 0
+#define USE_TRUNCATE(...)
+#define CFG_TS 0
+#define USE_TS(...)
+#define CFG_UCLAMPSET 0
+#define USE_UCLAMPSET(...)
+#define CFG_UPTIME 0
+#define USE_UPTIME(...)
+#define CFG_USLEEP 0
+#define USE_USLEEP(...)
+#define CFG_UUIDGEN 0
+#define USE_UUIDGEN(...)
+#define CFG_VCONFIG 0
+#define USE_VCONFIG(...)
+#define CFG_VMSTAT 0
+#define USE_VMSTAT(...)
+#define CFG_W 0
+#define USE_W(...)
+#define CFG_WATCH 0
+#define USE_WATCH(...)
+#define CFG_WATCHDOG 0
+#define USE_WATCHDOG(...)
+#define CFG_WHICH 1
+#define USE_WHICH(...) __VA_ARGS__
+#define CFG_XXD 0
+#define USE_XXD(...)
+#define CFG_YES 0
+#define USE_YES(...)
+#define CFG_FTPGET 0
+#define USE_FTPGET(...)
+#define CFG_FTPPUT 0
+#define USE_FTPPUT(...)
+#define CFG_HOST 0
+#define USE_HOST(...)
+#define CFG_HTTPD 0
+#define USE_HTTPD(...)
+#define CFG_IFCONFIG 0
+#define USE_IFCONFIG(...)
+#define CFG_MICROCOM 0
+#define USE_MICROCOM(...)
+#define CFG_NETCAT 0
+#define USE_NETCAT(...)
+#define CFG_NETSTAT 0
+#define USE_NETSTAT(...)
+#define CFG_PING 0
+#define USE_PING(...)
+#define CFG_RFKILL 0
+#define USE_RFKILL(...)
+#define CFG_SNTP 0
+#define USE_SNTP(...)
+#define CFG_TUNCTL 0
+#define USE_TUNCTL(...)
+#define CFG_WGET 0
+#define USE_WGET(...)
+#define CFG_WGET_LIBTLS 0
+#define USE_WGET_LIBTLS(...)
+#define CFG_DMESG 0
+#define USE_DMESG(...)
+#define CFG_GZIP 1
+#define USE_GZIP(...) __VA_ARGS__
+#define CFG_GUNZIP 0
+#define USE_GUNZIP(...)
+#define CFG_ZCAT 0
+#define USE_ZCAT(...)
+#define CFG_HOSTNAME 0
+#define USE_HOSTNAME(...)
+#define CFG_DNSDOMAINNAME 0
+#define USE_DNSDOMAINNAME(...)
+#define CFG_KILLALL 0
+#define USE_KILLALL(...)
+#define CFG_MD5SUM 0
+#define USE_MD5SUM(...)
+#define CFG_SHA1SUM 0
+#define USE_SHA1SUM(...)
+#define CFG_SHA224SUM 0
+#define USE_SHA224SUM(...)
+#define CFG_SHA256SUM 0
+#define USE_SHA256SUM(...)
+#define CFG_SHA384SUM 0
+#define USE_SHA384SUM(...)
+#define CFG_SHA512SUM 0
+#define USE_SHA512SUM(...)
+#define CFG_MKNOD 0
+#define USE_MKNOD(...)
+#define CFG_MKNOD_Z 0
+#define USE_MKNOD_Z(...)
+#define CFG_MKTEMP 0
+#define USE_MKTEMP(...)
+#define CFG_MOUNT 0
+#define USE_MOUNT(...)
+#define CFG_PASSWD 0
+#define USE_PASSWD(...)
+#define CFG_PASSWD_SAD 0
+#define USE_PASSWD_SAD(...)
+#define CFG_PIDOF 0
+#define USE_PIDOF(...)
+#define CFG_SEQ 0
+#define USE_SEQ(...)
+#define CFG_SU 0
+#define USE_SU(...)
+#define CFG_SYNC 0
+#define USE_SYNC(...)
+#define CFG_UMOUNT 0
+#define USE_UMOUNT(...)
+#define CFG_DEMO_MANY_OPTIONS 0
+#define USE_DEMO_MANY_OPTIONS(...)
+#define CFG_DEMO_NUMBER 0
+#define USE_DEMO_NUMBER(...)
+#define CFG_DEMO_SCANKEY 0
+#define USE_DEMO_SCANKEY(...)
+#define CFG_DEMO_UTF8TOWC 0
+#define USE_DEMO_UTF8TOWC(...)
+#define CFG_HELLO 0
+#define USE_HELLO(...)
+#define CFG_HOSTID 0
+#define USE_HOSTID(...)
+#define CFG_LOGPATH 0
+#define USE_LOGPATH(...)
+#define CFG_SKELETON 0
+#define USE_SKELETON(...)
+#define CFG_SKELETON_ALIAS 0
+#define USE_SKELETON_ALIAS(...)
+#define CFG_GETENFORCE 0
+#define USE_GETENFORCE(...)
+#define CFG_LOAD_POLICY 0
+#define USE_LOAD_POLICY(...)
+#define CFG_LOG 0
+#define USE_LOG(...)
+#define CFG_RESTORECON 0
+#define USE_RESTORECON(...)
+#define CFG_RUNCON 0
+#define USE_RUNCON(...)
+#define CFG_SENDEVENT 0
+#define USE_SENDEVENT(...)
+#define CFG_SETENFORCE 0
+#define USE_SETENFORCE(...)
+#define CFG_TOYBOX 1
+#define USE_TOYBOX(...) __VA_ARGS__
+#define CFG_TOYBOX_SUID 0
+#define USE_TOYBOX_SUID(...)
+#define CFG_TOYBOX_LSM_NONE 1
+#define USE_TOYBOX_LSM_NONE(...) __VA_ARGS__
+#define CFG_TOYBOX_SELINUX 0
+#define USE_TOYBOX_SELINUX(...)
+#define CFG_TOYBOX_SMACK 0
+#define USE_TOYBOX_SMACK(...)
+#define CFG_TOYBOX_LIBCRYPTO 0
+#define USE_TOYBOX_LIBCRYPTO(...)
+#define CFG_TOYBOX_LIBZ 0
+#define USE_TOYBOX_LIBZ(...)
+#define CFG_TOYBOX_FLOAT 0
+#define USE_TOYBOX_FLOAT(...)
+#define CFG_TOYBOX_HELP 0
+#define USE_TOYBOX_HELP(...)
+#define CFG_TOYBOX_HELP_DASHDASH 0
+#define USE_TOYBOX_HELP_DASHDASH(...)
+#define CFG_TOYBOX_ZHELP 0
+#define USE_TOYBOX_ZHELP(...)
+#define CFG_TOYBOX_FREE 0
+#define USE_TOYBOX_FREE(...)
+#define CFG_TOYBOX_NORECURSE 0
+#define USE_TOYBOX_NORECURSE(...)
+#define CFG_TOYBOX_DEBUG 0
+#define USE_TOYBOX_DEBUG(...)
+#define CFG_TOYBOX_UID_SYS 100
+#define CFG_TOYBOX_UID_USR 500
+#define CFG_TOYBOX_FORCE_NOMMU 0
+#define USE_TOYBOX_FORCE_NOMMU(...)
diff --git a/scripts/prereq/generated/flags.h b/scripts/prereq/generated/flags.h
new file mode 100644
index 00000000..811899dd
--- /dev/null
+++ b/scripts/prereq/generated/flags.h
@@ -0,0 +1,827 @@
+#undef FORCED_FLAG
+#ifdef FORCE_FLAGS
+#define FORCED_FLAG 1LL
+#else
+#define FORCED_FLAG 0LL
+#endif
+
+// basename ^<1as: ^<1as:
+#undef OPTSTR_basename
+#define OPTSTR_basename "^<1as:"
+#ifdef CLEANUP_basename
+#undef CLEANUP_basename
+#undef FOR_basename
+#undef FLAG_s
+#undef FLAG_a
+#endif
+
+// cat uvte uvte
+#undef OPTSTR_cat
+#define OPTSTR_cat "uvte"
+#ifdef CLEANUP_cat
+#undef CLEANUP_cat
+#undef FOR_cat
+#undef FLAG_e
+#undef FLAG_t
+#undef FLAG_v
+#undef FLAG_u
+#endif
+
+// chmod <2?vfR[-vf] <2?vfR[-vf]
+#undef OPTSTR_chmod
+#define OPTSTR_chmod "<2?vfR[-vf]"
+#ifdef CLEANUP_chmod
+#undef CLEANUP_chmod
+#undef FOR_chmod
+#undef FLAG_R
+#undef FLAG_f
+#undef FLAG_v
+#endif
+
+// cmp <1>4ls(silent)(quiet)n#<1[!ls] <1>4ls(silent)(quiet)n#<1[!ls]
+#undef OPTSTR_cmp
+#define OPTSTR_cmp "<1>4ls(silent)(quiet)n#<1[!ls]"
+#ifdef CLEANUP_cmp
+#undef CLEANUP_cmp
+#undef FOR_cmp
+#undef FLAG_n
+#undef FLAG_s
+#undef FLAG_l
+#endif
+
+// echo ^?Een[-eE] ^?Een[-eE]
+#undef OPTSTR_echo
+#define OPTSTR_echo "^?Een[-eE]"
+#ifdef CLEANUP_echo
+#undef CLEANUP_echo
+#undef FOR_echo
+#undef FLAG_n
+#undef FLAG_e
+#undef FLAG_E
+#endif
+
+// fold bsw#<1=80 bsw#<1=80
+#undef OPTSTR_fold
+#define OPTSTR_fold "bsw#<1=80"
+#ifdef CLEANUP_fold
+#undef CLEANUP_fold
+#undef FOR_fold
+#undef FLAG_w
+#undef FLAG_s
+#undef FLAG_b
+#endif
+
+// grep (line-buffered)(color):;(exclude-dir)*S(exclude)*M(include)*ZzEFHIab(byte-offset)h(no-filename)ino(only-matching)rRsvwc(count)L(files-without-match)l(files-with-matches)q(quiet)(silent)e*f*C#B#A#m#x[!wx][!EF] (line-buffered)(color):;(exclude-dir)*S(exclude)*M(include)*ZzEFHIab(byte-offset)h(no-filename)ino(only-matching)rRsvwc(count)L(files-without-match)l(files-with-matches)q(quiet)(silent)e*f*C#B#A#m#x[!wx][!EF]
+#undef OPTSTR_grep
+#define OPTSTR_grep "(line-buffered)(color):;(exclude-dir)*S(exclude)*M(include)*ZzEFHIab(byte-offset)h(no-filename)ino(only-matching)rRsvwc(count)L(files-without-match)l(files-with-matches)q(quiet)(silent)e*f*C#B#A#m#x[!wx][!EF]"
+#ifdef CLEANUP_grep
+#undef CLEANUP_grep
+#undef FOR_grep
+#undef FLAG_x
+#undef FLAG_m
+#undef FLAG_A
+#undef FLAG_B
+#undef FLAG_C
+#undef FLAG_f
+#undef FLAG_e
+#undef FLAG_q
+#undef FLAG_l
+#undef FLAG_L
+#undef FLAG_c
+#undef FLAG_w
+#undef FLAG_v
+#undef FLAG_s
+#undef FLAG_R
+#undef FLAG_r
+#undef FLAG_o
+#undef FLAG_n
+#undef FLAG_i
+#undef FLAG_h
+#undef FLAG_b
+#undef FLAG_a
+#undef FLAG_I
+#undef FLAG_H
+#undef FLAG_F
+#undef FLAG_E
+#undef FLAG_z
+#undef FLAG_Z
+#undef FLAG_M
+#undef FLAG_S
+#undef FLAG_exclude_dir
+#undef FLAG_color
+#undef FLAG_line_buffered
+#endif
+
+// gzip n(no-name)cdfkt123456789[-123456789] n(no-name)cdfkt123456789[-123456789]
+#undef OPTSTR_gzip
+#define OPTSTR_gzip "n(no-name)cdfkt123456789[-123456789]"
+#ifdef CLEANUP_gzip
+#undef CLEANUP_gzip
+#undef FOR_gzip
+#undef FLAG_9
+#undef FLAG_8
+#undef FLAG_7
+#undef FLAG_6
+#undef FLAG_5
+#undef FLAG_4
+#undef FLAG_3
+#undef FLAG_2
+#undef FLAG_1
+#undef FLAG_t
+#undef FLAG_k
+#undef FLAG_f
+#undef FLAG_d
+#undef FLAG_c
+#undef FLAG_n
+#endif
+
+// head ?n(lines)#<0=10c(bytes)#<0qv[-nc] ?n(lines)#<0=10c(bytes)#<0qv[-nc]
+#undef OPTSTR_head
+#define OPTSTR_head "?n(lines)#<0=10c(bytes)#<0qv[-nc]"
+#ifdef CLEANUP_head
+#undef CLEANUP_head
+#undef FOR_head
+#undef FLAG_v
+#undef FLAG_q
+#undef FLAG_c
+#undef FLAG_n
+#endif
+
+// ln <1rt:Tvnfs <1rt:Tvnfs
+#undef OPTSTR_ln
+#define OPTSTR_ln "<1rt:Tvnfs"
+#ifdef CLEANUP_ln
+#undef CLEANUP_ln
+#undef FOR_ln
+#undef FLAG_s
+#undef FLAG_f
+#undef FLAG_n
+#undef FLAG_v
+#undef FLAG_T
+#undef FLAG_t
+#undef FLAG_r
+#endif
+
+// ls (sort):(color):;(full-time)(show-control-chars)ÿ(block-size)#=1024<1¡(group-directories-first)þZgoACFHLNRSUXabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][-Nqb][-kÿ] (sort):(color):;(full-time)(show-control-chars)ÿ(block-size)#=1024<1¡(group-directories-first)þZgoACFHLNRSUXabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][-Nqb][-kÿ]
+#undef OPTSTR_ls
+#define OPTSTR_ls "(sort):(color):;(full-time)(show-control-chars)ÿ(block-size)#=1024<1¡(group-directories-first)þZgoACFHLNRSUXabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][-Nqb][-kÿ]"
+#ifdef CLEANUP_ls
+#undef CLEANUP_ls
+#undef FOR_ls
+#undef FLAG_1
+#undef FLAG_x
+#undef FLAG_w
+#undef FLAG_u
+#undef FLAG_t
+#undef FLAG_s
+#undef FLAG_r
+#undef FLAG_q
+#undef FLAG_p
+#undef FLAG_n
+#undef FLAG_m
+#undef FLAG_l
+#undef FLAG_k
+#undef FLAG_i
+#undef FLAG_h
+#undef FLAG_f
+#undef FLAG_d
+#undef FLAG_c
+#undef FLAG_b
+#undef FLAG_a
+#undef FLAG_X
+#undef FLAG_U
+#undef FLAG_S
+#undef FLAG_R
+#undef FLAG_N
+#undef FLAG_L
+#undef FLAG_H
+#undef FLAG_F
+#undef FLAG_C
+#undef FLAG_A
+#undef FLAG_o
+#undef FLAG_g
+#undef FLAG_Z
+#undef FLAG_X7E
+#undef FLAG_X21
+#undef FLAG_X7F
+#undef FLAG_show_control_chars
+#undef FLAG_full_time
+#undef FLAG_color
+#undef FLAG_sort
+#endif
+
+// mkdir <1vp(parent)(parents)m: <1Z:vp(parent)(parents)m:
+#undef OPTSTR_mkdir
+#define OPTSTR_mkdir "<1vp(parent)(parents)m:"
+#ifdef CLEANUP_mkdir
+#undef CLEANUP_mkdir
+#undef FOR_mkdir
+#undef FLAG_m
+#undef FLAG_p
+#undef FLAG_v
+#undef FLAG_Z
+#endif
+
+// od j#vw#<1=16N#xsodcbA:t* j#vw#<1=16N#xsodcbA:t*
+#undef OPTSTR_od
+#define OPTSTR_od "j#vw#<1=16N#xsodcbA:t*"
+#ifdef CLEANUP_od
+#undef CLEANUP_od
+#undef FOR_od
+#undef FLAG_t
+#undef FLAG_A
+#undef FLAG_b
+#undef FLAG_c
+#undef FLAG_d
+#undef FLAG_o
+#undef FLAG_s
+#undef FLAG_x
+#undef FLAG_N
+#undef FLAG_w
+#undef FLAG_v
+#undef FLAG_j
+#endif
+
+// readlink <1vnf(canonicalize)emqz[-mef][-qv] <1vnf(canonicalize)emqz[-mef][-qv]
+#undef OPTSTR_readlink
+#define OPTSTR_readlink "<1vnf(canonicalize)emqz[-mef][-qv]"
+#ifdef CLEANUP_readlink
+#undef CLEANUP_readlink
+#undef FOR_readlink
+#undef FLAG_z
+#undef FLAG_q
+#undef FLAG_m
+#undef FLAG_e
+#undef FLAG_f
+#undef FLAG_n
+#undef FLAG_v
+#endif
+
+// realpath <1(relative-base):R(relative-to):s(no-symlinks)LPemqz[-Ps][-LP][-me]
+#undef OPTSTR_realpath
+#define OPTSTR_realpath "<1(relative-base):R(relative-to):s(no-symlinks)LPemqz[-Ps][-LP][-me]"
+#ifdef CLEANUP_realpath
+#undef CLEANUP_realpath
+#undef FOR_realpath
+#undef FLAG_z
+#undef FLAG_q
+#undef FLAG_m
+#undef FLAG_e
+#undef FLAG_P
+#undef FLAG_L
+#undef FLAG_s
+#undef FLAG_R
+#undef FLAG_relative_base
+#endif
+
+// rm f(force)iRrv[-fi] f(force)iRrv[-fi]
+#undef OPTSTR_rm
+#define OPTSTR_rm "f(force)iRrv[-fi]"
+#ifdef CLEANUP_rm
+#undef CLEANUP_rm
+#undef FOR_rm
+#undef FLAG_v
+#undef FLAG_r
+#undef FLAG_R
+#undef FLAG_i
+#undef FLAG_f
+#endif
+
+// sed (help)(version)(tarxform)e*f*i:;nErz(null-data)s[+Er] (help)(version)(tarxform)e*f*i:;nErz(null-data)s[+Er]
+#undef OPTSTR_sed
+#define OPTSTR_sed "(help)(version)(tarxform)e*f*i:;nErz(null-data)s[+Er]"
+#ifdef CLEANUP_sed
+#undef CLEANUP_sed
+#undef FOR_sed
+#undef FLAG_s
+#undef FLAG_z
+#undef FLAG_r
+#undef FLAG_E
+#undef FLAG_n
+#undef FLAG_i
+#undef FLAG_f
+#undef FLAG_e
+#undef FLAG_tarxform
+#undef FLAG_version
+#undef FLAG_help
+#endif
+
+// sort S:T:mo:k*t:xVbMCcszdfirun gS:T:mo:k*t:xVbMCcszdfirun
+#undef OPTSTR_sort
+#define OPTSTR_sort "S:T:mo:k*t:xVbMCcszdfirun"
+#ifdef CLEANUP_sort
+#undef CLEANUP_sort
+#undef FOR_sort
+#undef FLAG_n
+#undef FLAG_u
+#undef FLAG_r
+#undef FLAG_i
+#undef FLAG_f
+#undef FLAG_d
+#undef FLAG_z
+#undef FLAG_s
+#undef FLAG_c
+#undef FLAG_C
+#undef FLAG_M
+#undef FLAG_b
+#undef FLAG_V
+#undef FLAG_x
+#undef FLAG_t
+#undef FLAG_k
+#undef FLAG_o
+#undef FLAG_m
+#undef FLAG_T
+#undef FLAG_S
+#undef FLAG_g
+#endif
+
+// tail ?fFs:c(bytes)-n(lines)-[-cn][-fF] ?fFs:c(bytes)-n(lines)-[-cn][-fF]
+#undef OPTSTR_tail
+#define OPTSTR_tail "?fFs:c(bytes)-n(lines)-[-cn][-fF]"
+#ifdef CLEANUP_tail
+#undef CLEANUP_tail
+#undef FOR_tail
+#undef FLAG_n
+#undef FLAG_c
+#undef FLAG_s
+#undef FLAG_F
+#undef FLAG_f
+#endif
+
+// tee ia ia
+#undef OPTSTR_tee
+#define OPTSTR_tee "ia"
+#ifdef CLEANUP_tee
+#undef CLEANUP_tee
+#undef FOR_tee
+#undef FLAG_a
+#undef FLAG_i
+#endif
+
+// tr ^<1>2Ccstd[+cC] ^<1>2Ccstd[+cC]
+#undef OPTSTR_tr
+#define OPTSTR_tr "^<1>2Ccstd[+cC]"
+#ifdef CLEANUP_tr
+#undef CLEANUP_tr
+#undef FOR_tr
+#undef FLAG_d
+#undef FLAG_t
+#undef FLAG_s
+#undef FLAG_c
+#undef FLAG_C
+#endif
+
+// uname paomvrns paomvrns
+#undef OPTSTR_uname
+#define OPTSTR_uname "paomvrns"
+#ifdef CLEANUP_uname
+#undef CLEANUP_uname
+#undef FOR_uname
+#undef FLAG_s
+#undef FLAG_n
+#undef FLAG_r
+#undef FLAG_v
+#undef FLAG_m
+#undef FLAG_o
+#undef FLAG_a
+#undef FLAG_p
+#endif
+
+// wc Lcmwl Lcmwl
+#undef OPTSTR_wc
+#define OPTSTR_wc "Lcmwl"
+#ifdef CLEANUP_wc
+#undef CLEANUP_wc
+#undef FOR_wc
+#undef FLAG_l
+#undef FLAG_w
+#undef FLAG_m
+#undef FLAG_c
+#undef FLAG_L
+#endif
+
+// xargs ^E:P#<0(null)=1optr(no-run-if-empty)n#<1(max-args)s#0[!0E] ^E:P#<0(null)=1optr(no-run-if-empty)n#<1(max-args)s#0[!0E]
+#undef OPTSTR_xargs
+#define OPTSTR_xargs "^E:P#<0(null)=1optr(no-run-if-empty)n#<1(max-args)s#0[!0E]"
+#ifdef CLEANUP_xargs
+#undef CLEANUP_xargs
+#undef FOR_xargs
+#undef FLAG_0
+#undef FLAG_s
+#undef FLAG_n
+#undef FLAG_r
+#undef FLAG_t
+#undef FLAG_p
+#undef FLAG_o
+#undef FLAG_P
+#undef FLAG_E
+#endif
+
+#ifdef FOR_basename
+#define CLEANUP_basename
+#ifndef TT
+#define TT this.basename
+#endif
+#define FLAG_s (1LL<<0)
+#define FLAG_a (1LL<<1)
+#endif
+
+#ifdef FOR_cat
+#define CLEANUP_cat
+#ifndef TT
+#define TT this.cat
+#endif
+#define FLAG_e (1LL<<0)
+#define FLAG_t (1LL<<1)
+#define FLAG_v (1LL<<2)
+#define FLAG_u (1LL<<3)
+#endif
+
+#ifdef FOR_chmod
+#define CLEANUP_chmod
+#ifndef TT
+#define TT this.chmod
+#endif
+#define FLAG_R (1LL<<0)
+#define FLAG_f (1LL<<1)
+#define FLAG_v (1LL<<2)
+#endif
+
+#ifdef FOR_cmp
+#define CLEANUP_cmp
+#ifndef TT
+#define TT this.cmp
+#endif
+#define FLAG_n (1LL<<0)
+#define FLAG_s (1LL<<1)
+#define FLAG_l (1LL<<2)
+#endif
+
+#ifdef FOR_echo
+#define CLEANUP_echo
+#ifndef TT
+#define TT this.echo
+#endif
+#define FLAG_n (1LL<<0)
+#define FLAG_e (1LL<<1)
+#define FLAG_E (1LL<<2)
+#endif
+
+#ifdef FOR_fold
+#define CLEANUP_fold
+#ifndef TT
+#define TT this.fold
+#endif
+#define FLAG_w (1LL<<0)
+#define FLAG_s (1LL<<1)
+#define FLAG_b (1LL<<2)
+#endif
+
+#ifdef FOR_grep
+#define CLEANUP_grep
+#ifndef TT
+#define TT this.grep
+#endif
+#define FLAG_x (1LL<<0)
+#define FLAG_m (1LL<<1)
+#define FLAG_A (1LL<<2)
+#define FLAG_B (1LL<<3)
+#define FLAG_C (1LL<<4)
+#define FLAG_f (1LL<<5)
+#define FLAG_e (1LL<<6)
+#define FLAG_q (1LL<<7)
+#define FLAG_l (1LL<<8)
+#define FLAG_L (1LL<<9)
+#define FLAG_c (1LL<<10)
+#define FLAG_w (1LL<<11)
+#define FLAG_v (1LL<<12)
+#define FLAG_s (1LL<<13)
+#define FLAG_R (1LL<<14)
+#define FLAG_r (1LL<<15)
+#define FLAG_o (1LL<<16)
+#define FLAG_n (1LL<<17)
+#define FLAG_i (1LL<<18)
+#define FLAG_h (1LL<<19)
+#define FLAG_b (1LL<<20)
+#define FLAG_a (1LL<<21)
+#define FLAG_I (1LL<<22)
+#define FLAG_H (1LL<<23)
+#define FLAG_F (1LL<<24)
+#define FLAG_E (1LL<<25)
+#define FLAG_z (1LL<<26)
+#define FLAG_Z (1LL<<27)
+#define FLAG_M (1LL<<28)
+#define FLAG_S (1LL<<29)
+#define FLAG_exclude_dir (1LL<<30)
+#define FLAG_color (1LL<<31)
+#define FLAG_line_buffered (1LL<<32)
+#endif
+
+#ifdef FOR_gzip
+#define CLEANUP_gzip
+#ifndef TT
+#define TT this.gzip
+#endif
+#define FLAG_9 (1LL<<0)
+#define FLAG_8 (1LL<<1)
+#define FLAG_7 (1LL<<2)
+#define FLAG_6 (1LL<<3)
+#define FLAG_5 (1LL<<4)
+#define FLAG_4 (1LL<<5)
+#define FLAG_3 (1LL<<6)
+#define FLAG_2 (1LL<<7)
+#define FLAG_1 (1LL<<8)
+#define FLAG_t (1LL<<9)
+#define FLAG_k (1LL<<10)
+#define FLAG_f (1LL<<11)
+#define FLAG_d (1LL<<12)
+#define FLAG_c (1LL<<13)
+#define FLAG_n (1LL<<14)
+#endif
+
+#ifdef FOR_head
+#define CLEANUP_head
+#ifndef TT
+#define TT this.head
+#endif
+#define FLAG_v (1LL<<0)
+#define FLAG_q (1LL<<1)
+#define FLAG_c (1LL<<2)
+#define FLAG_n (1LL<<3)
+#endif
+
+#ifdef FOR_ln
+#define CLEANUP_ln
+#ifndef TT
+#define TT this.ln
+#endif
+#define FLAG_s (1LL<<0)
+#define FLAG_f (1LL<<1)
+#define FLAG_n (1LL<<2)
+#define FLAG_v (1LL<<3)
+#define FLAG_T (1LL<<4)
+#define FLAG_t (1LL<<5)
+#define FLAG_r (1LL<<6)
+#endif
+
+#ifdef FOR_ls
+#define CLEANUP_ls
+#ifndef TT
+#define TT this.ls
+#endif
+#define FLAG_1 (1LL<<0)
+#define FLAG_x (1LL<<1)
+#define FLAG_w (1LL<<2)
+#define FLAG_u (1LL<<3)
+#define FLAG_t (1LL<<4)
+#define FLAG_s (1LL<<5)
+#define FLAG_r (1LL<<6)
+#define FLAG_q (1LL<<7)
+#define FLAG_p (1LL<<8)
+#define FLAG_n (1LL<<9)
+#define FLAG_m (1LL<<10)
+#define FLAG_l (1LL<<11)
+#define FLAG_k (1LL<<12)
+#define FLAG_i (1LL<<13)
+#define FLAG_h (1LL<<14)
+#define FLAG_f (1LL<<15)
+#define FLAG_d (1LL<<16)
+#define FLAG_c (1LL<<17)
+#define FLAG_b (1LL<<18)
+#define FLAG_a (1LL<<19)
+#define FLAG_X (1LL<<20)
+#define FLAG_U (1LL<<21)
+#define FLAG_S (1LL<<22)
+#define FLAG_R (1LL<<23)
+#define FLAG_N (1LL<<24)
+#define FLAG_L (1LL<<25)
+#define FLAG_H (1LL<<26)
+#define FLAG_F (1LL<<27)
+#define FLAG_C (1LL<<28)
+#define FLAG_A (1LL<<29)
+#define FLAG_o (1LL<<30)
+#define FLAG_g (1LL<<31)
+#define FLAG_Z (1LL<<32)
+#define FLAG_X7E (1LL<<33)
+#define FLAG_X21 (1LL<<34)
+#define FLAG_X7F (1LL<<35)
+#define FLAG_show_control_chars (1LL<<36)
+#define FLAG_full_time (1LL<<37)
+#define FLAG_color (1LL<<38)
+#define FLAG_sort (1LL<<39)
+#endif
+
+#ifdef FOR_mkdir
+#define CLEANUP_mkdir
+#ifndef TT
+#define TT this.mkdir
+#endif
+#define FLAG_m (1LL<<0)
+#define FLAG_p (1LL<<1)
+#define FLAG_v (1LL<<2)
+#define FLAG_Z (FORCED_FLAG<<3)
+#endif
+
+#ifdef FOR_od
+#define CLEANUP_od
+#ifndef TT
+#define TT this.od
+#endif
+#define FLAG_t (1LL<<0)
+#define FLAG_A (1LL<<1)
+#define FLAG_b (1LL<<2)
+#define FLAG_c (1LL<<3)
+#define FLAG_d (1LL<<4)
+#define FLAG_o (1LL<<5)
+#define FLAG_s (1LL<<6)
+#define FLAG_x (1LL<<7)
+#define FLAG_N (1LL<<8)
+#define FLAG_w (1LL<<9)
+#define FLAG_v (1LL<<10)
+#define FLAG_j (1LL<<11)
+#endif
+
+#ifdef FOR_readlink
+#define CLEANUP_readlink
+#ifndef TT
+#define TT this.readlink
+#endif
+#define FLAG_z (1LL<<0)
+#define FLAG_q (1LL<<1)
+#define FLAG_m (1LL<<2)
+#define FLAG_e (1LL<<3)
+#define FLAG_f (1LL<<4)
+#define FLAG_n (1LL<<5)
+#define FLAG_v (1LL<<6)
+#endif
+
+#ifdef FOR_realpath
+#define CLEANUP_realpath
+#ifndef TT
+#define TT this.realpath
+#endif
+#define FLAG_z (FORCED_FLAG<<0)
+#define FLAG_q (FORCED_FLAG<<1)
+#define FLAG_m (FORCED_FLAG<<2)
+#define FLAG_e (FORCED_FLAG<<3)
+#define FLAG_P (FORCED_FLAG<<4)
+#define FLAG_L (FORCED_FLAG<<5)
+#define FLAG_s (FORCED_FLAG<<6)
+#define FLAG_R (FORCED_FLAG<<7)
+#define FLAG_relative_base (FORCED_FLAG<<8)
+#endif
+
+#ifdef FOR_rm
+#define CLEANUP_rm
+#ifndef TT
+#define TT this.rm
+#endif
+#define FLAG_v (1LL<<0)
+#define FLAG_r (1LL<<1)
+#define FLAG_R (1LL<<2)
+#define FLAG_i (1LL<<3)
+#define FLAG_f (1LL<<4)
+#endif
+
+#ifdef FOR_sed
+#define CLEANUP_sed
+#ifndef TT
+#define TT this.sed
+#endif
+#define FLAG_s (1LL<<0)
+#define FLAG_z (1LL<<1)
+#define FLAG_r (1LL<<2)
+#define FLAG_E (1LL<<3)
+#define FLAG_n (1LL<<4)
+#define FLAG_i (1LL<<5)
+#define FLAG_f (1LL<<6)
+#define FLAG_e (1LL<<7)
+#define FLAG_tarxform (1LL<<8)
+#define FLAG_version (1LL<<9)
+#define FLAG_help (1LL<<10)
+#endif
+
+#ifdef FOR_sort
+#define CLEANUP_sort
+#ifndef TT
+#define TT this.sort
+#endif
+#define FLAG_n (1LL<<0)
+#define FLAG_u (1LL<<1)
+#define FLAG_r (1LL<<2)
+#define FLAG_i (1LL<<3)
+#define FLAG_f (1LL<<4)
+#define FLAG_d (1LL<<5)
+#define FLAG_z (1LL<<6)
+#define FLAG_s (1LL<<7)
+#define FLAG_c (1LL<<8)
+#define FLAG_C (1LL<<9)
+#define FLAG_M (1LL<<10)
+#define FLAG_b (1LL<<11)
+#define FLAG_V (1LL<<12)
+#define FLAG_x (1LL<<13)
+#define FLAG_t (1LL<<14)
+#define FLAG_k (1LL<<15)
+#define FLAG_o (1LL<<16)
+#define FLAG_m (1LL<<17)
+#define FLAG_T (1LL<<18)
+#define FLAG_S (1LL<<19)
+#define FLAG_g (FORCED_FLAG<<20)
+#endif
+
+#ifdef FOR_tail
+#define CLEANUP_tail
+#ifndef TT
+#define TT this.tail
+#endif
+#define FLAG_n (1LL<<0)
+#define FLAG_c (1LL<<1)
+#define FLAG_s (1LL<<2)
+#define FLAG_F (1LL<<3)
+#define FLAG_f (1LL<<4)
+#endif
+
+#ifdef FOR_tee
+#define CLEANUP_tee
+#ifndef TT
+#define TT this.tee
+#endif
+#define FLAG_a (1LL<<0)
+#define FLAG_i (1LL<<1)
+#endif
+
+#ifdef FOR_tr
+#define CLEANUP_tr
+#ifndef TT
+#define TT this.tr
+#endif
+#define FLAG_d (1LL<<0)
+#define FLAG_t (1LL<<1)
+#define FLAG_s (1LL<<2)
+#define FLAG_c (1LL<<3)
+#define FLAG_C (1LL<<4)
+#endif
+
+#ifdef FOR_uname
+#define CLEANUP_uname
+#ifndef TT
+#define TT this.uname
+#endif
+#define FLAG_s (1LL<<0)
+#define FLAG_n (1LL<<1)
+#define FLAG_r (1LL<<2)
+#define FLAG_v (1LL<<3)
+#define FLAG_m (1LL<<4)
+#define FLAG_o (1LL<<5)
+#define FLAG_a (1LL<<6)
+#define FLAG_p (1LL<<7)
+#endif
+
+#ifdef FOR_wc
+#define CLEANUP_wc
+#ifndef TT
+#define TT this.wc
+#endif
+#define FLAG_l (1LL<<0)
+#define FLAG_w (1LL<<1)
+#define FLAG_m (1LL<<2)
+#define FLAG_c (1LL<<3)
+#define FLAG_L (1LL<<4)
+#endif
+
+#ifdef FOR_xargs
+#define CLEANUP_xargs
+#ifndef TT
+#define TT this.xargs
+#endif
+#define FLAG_0 (1LL<<0)
+#define FLAG_s (1LL<<1)
+#define FLAG_n (1LL<<2)
+#define FLAG_r (1LL<<3)
+#define FLAG_t (1LL<<4)
+#define FLAG_p (1LL<<5)
+#define FLAG_o (1LL<<6)
+#define FLAG_P (1LL<<7)
+#define FLAG_E (1LL<<8)
+#endif
+
+#undef OPTSTR_ascii
+#define OPTSTR_ascii 0
+#undef OPTSTR_dirname
+#define OPTSTR_dirname "<1"
+#undef OPTSTR_gitcheckout
+#define OPTSTR_gitcheckout "<1"
+#undef OPTSTR_gitclone
+#define OPTSTR_gitclone "<1"
+#undef OPTSTR_gitfetch
+#define OPTSTR_gitfetch 0
+#undef OPTSTR_gitinit
+#define OPTSTR_gitinit "<1"
+#undef OPTSTR_gitremote
+#define OPTSTR_gitremote "<1"
+#undef OPTSTR_makedevs
+#define OPTSTR_makedevs "<1>1d:"
+#undef OPTSTR_toybox
+#define OPTSTR_toybox 0
+#undef OPTSTR_which
+#define OPTSTR_which "<1a"
diff --git a/scripts/prereq/generated/globals.h b/scripts/prereq/generated/globals.h
new file mode 100644
index 00000000..464bfd70
--- /dev/null
+++ b/scripts/prereq/generated/globals.h
@@ -0,0 +1,155 @@
+struct gzip_data {
+ int level;
+};
+
+struct realpath_data {
+ char *R, *relative_base;
+};
+
+struct tr_data {
+ short *map;
+ int len1, len2;
+};
+
+struct basename_data {
+ char *s;
+};
+
+struct chmod_data {
+ char *mode;
+};
+
+struct cmp_data {
+ long n;
+
+ int fd;
+ char *name;
+};
+
+struct fold_data {
+ long w;
+};
+
+struct grep_data {
+ long m, A, B, C;
+ struct arg_list *f, *e, *M, *S, *exclude_dir;
+ char *color;
+
+ char *purple, *cyan, *red, *green, *grey;
+ struct double_list *reg;
+ int found, tried, delim;
+ struct arg_list **fixed;
+};
+
+struct head_data {
+ long c, n;
+
+ int file_no;
+};
+
+struct ln_data {
+ char *t;
+};
+
+struct ls_data {
+ long w, l, block_size;
+ char *color, *sort;
+
+ struct dirtree *files, *singledir;
+ unsigned screen_width;
+ int nl_title;
+ char *escmore;
+};
+
+struct mkdir_data {
+ char *m, *Z;
+};
+
+struct od_data {
+ struct arg_list *t;
+ char *A;
+ long N, w, j;
+
+ int address_idx;
+ unsigned types, leftover, star;
+ char *buf; // Points to buffers[0] or buffers[1].
+ char *bufs[2]; // Used to detect duplicate lines.
+ off_t pos;
+};
+
+struct sed_data {
+ char *i;
+ struct arg_list *f, *e;
+
+ // processed pattern list
+ struct double_list *pattern;
+
+ char *nextline, *remember, *tarxform;
+ void *restart, *lastregex;
+ long nextlen, rememberlen, count;
+ int fdout, noeol;
+ unsigned xx, tarxlen, xflags;
+ char delim, xftype;
+};
+
+struct sort_data {
+ char *t;
+ struct arg_list *k;
+ char *o, *T, S;
+
+ void *key_list;
+ unsigned linecount;
+ char **lines, *name;
+};
+
+struct tail_data {
+ long n, c;
+ char *s;
+
+ int file_no, last_fd, ss;
+ struct xnotify *not;
+ struct {
+ char *path;
+ int fd;
+ struct dev_ino di;
+ } *F;
+};
+
+struct tee_data {
+ void *outputs;
+ int out;
+};
+
+struct wc_data {
+ unsigned long totals[5];
+};
+
+struct xargs_data {
+ long s, n, P;
+ char *E;
+
+ long entries, bytes, np;
+ char delim;
+ FILE *tty;
+};
+extern union global_union {
+ struct gzip_data gzip;
+ struct realpath_data realpath;
+ struct tr_data tr;
+ struct basename_data basename;
+ struct chmod_data chmod;
+ struct cmp_data cmp;
+ struct fold_data fold;
+ struct grep_data grep;
+ struct head_data head;
+ struct ln_data ln;
+ struct ls_data ls;
+ struct mkdir_data mkdir;
+ struct od_data od;
+ struct sed_data sed;
+ struct sort_data sort;
+ struct tail_data tail;
+ struct tee_data tee;
+ struct wc_data wc;
+ struct xargs_data xargs;
+} this;
diff --git a/scripts/prereq/generated/help.h b/scripts/prereq/generated/help.h
new file mode 100644
index 00000000..4457710d
--- /dev/null
+++ b/scripts/prereq/generated/help.h
@@ -0,0 +1,33 @@
+#define HELP_toybox ""
+#define HELP_as ""
+#define HELP_basename ""
+#define HELP_cat ""
+#define HELP_cc ""
+#define HELP_chmod ""
+#define HELP_cmp ""
+#define HELP_dirname ""
+#define HELP_echo ""
+#define HELP_egrep ""
+#define HELP_fold ""
+#define HELP_git ""
+#define HELP_grep ""
+#define HELP_gzip ""
+#define HELP_head ""
+#define HELP_ld ""
+#define HELP_ln ""
+#define HELP_ls ""
+#define HELP_make ""
+#define HELP_mkdir ""
+#define HELP_od ""
+#define HELP_readlink ""
+#define HELP_rm ""
+#define HELP_sed ""
+#define HELP_sort ""
+#define HELP_strip ""
+#define HELP_tail ""
+#define HELP_tee ""
+#define HELP_tr ""
+#define HELP_uname ""
+#define HELP_wc ""
+#define HELP_which ""
+#define HELP_xargs ""
diff --git a/scripts/prereq/generated/newtoys.h b/scripts/prereq/generated/newtoys.h
new file mode 100644
index 00000000..a9ed915d
--- /dev/null
+++ b/scripts/prereq/generated/newtoys.h
@@ -0,0 +1,123 @@
+USE_TOYBOX(NEWTOY(toybox, 0, TOYFLAG_STAYROOT|TOYFLAG_NOHELP))
+USE_SH(OLDTOY(-bash, sh, 0))
+USE_SH(OLDTOY(-sh, sh, 0))
+USE_SH(OLDTOY(-toysh, sh, 0))
+USE_SH(OLDTOY(., source, TOYFLAG_NOFORK))
+USE_TRUE(OLDTOY(:, true, TOYFLAG_NOFORK|TOYFLAG_NOHELP))
+USE_TEST_GLUE(OLDTOY([, test, TOYFLAG_BIN|TOYFLAG_MAYFORK|TOYFLAG_NOHELP))
+USE_SH(OLDTOY([[, test, TOYFLAG_NOFORK|TOYFLAG_NOHELP))
+USE_GROUPADD(OLDTOY(addgroup, groupadd, TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
+USE_USERADD(OLDTOY(adduser, useradd, TOYFLAG_NEEDROOT|TOYFLAG_UMASK|TOYFLAG_SBIN))
+USE_ASCII(NEWTOY(ascii, 0, TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
+USE_BASE32(NEWTOY(base32, "diw#<0=76[!dw]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
+USE_BASE64(NEWTOY(base64, "diw#<0=76[!dw]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
+USE_BASENAME(NEWTOY(basename, "^<1as:", TOYFLAG_USR|TOYFLAG_BIN))
+USE_SH(OLDTOY(bash, sh, TOYFLAG_BIN))
+USE_BZCAT(NEWTOY(bzcat, 0, TOYFLAG_USR|TOYFLAG_BIN))
+USE_CAT(NEWTOY(cat, "uvte", TOYFLAG_BIN))
+USE_CHATTR(NEWTOY(chattr, "?p#v#R", TOYFLAG_BIN))
+USE_CHMOD(NEWTOY(chmod, "<2?vfR[-vf]", TOYFLAG_BIN))
+USE_CHOWN(OLDTOY(chown, chgrp, TOYFLAG_BIN))
+USE_CKSUM(NEWTOY(cksum, "HIPLN", TOYFLAG_BIN))
+USE_CMP(NEWTOY(cmp, "<1>4ls(silent)(quiet)n#<1[!ls]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
+USE_CROND(NEWTOY(crond, "fbSl#<0=8d#<0L:c:[-bf][-LS][-ld]", TOYFLAG_USR|TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
+USE_GROUPDEL(OLDTOY(delgroup, groupdel, TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
+USE_USERDEL(OLDTOY(deluser, userdel, TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
+USE_DEMO_UTF8TOWC(NEWTOY(demo_utf8towc, 0, TOYFLAG_USR|TOYFLAG_BIN))
+USE_DIRNAME(NEWTOY(dirname, "<1", TOYFLAG_USR|TOYFLAG_BIN))
+USE_DUMPLEASES(NEWTOY(dumpleases, ">0arf:[!ar]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_ECHO(NEWTOY(echo, "^?Een[-eE]", TOYFLAG_BIN|TOYFLAG_MAYFORK|TOYFLAG_LINEBUF))
+USE_EGREP(OLDTOY(egrep, grep, TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)|TOYFLAG_LINEBUF))
+USE_FALLOCATE(NEWTOY(fallocate, ">1l#|o#", TOYFLAG_USR|TOYFLAG_BIN))
+USE_FALSE(NEWTOY(false, NULL, TOYFLAG_BIN|TOYFLAG_NOHELP|TOYFLAG_MAYFORK))
+USE_FGREP(OLDTOY(fgrep, grep, TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)|TOYFLAG_LINEBUF))
+USE_FOLD(NEWTOY(fold, "bsw#<1=80", TOYFLAG_USR|TOYFLAG_BIN))
+USE_FTPPUT(OLDTOY(ftpput, ftpget, TOYFLAG_USR|TOYFLAG_BIN))
+USE_GETFATTR(NEWTOY(getfattr, "(only-values)dhn:", TOYFLAG_USR|TOYFLAG_BIN))
+USE_GITCHECKOUT(NEWTOY(gitcheckout, "<1", TOYFLAG_USR|TOYFLAG_BIN))
+USE_GITCLONE(NEWTOY(gitclone, "<1", TOYFLAG_USR|TOYFLAG_BIN))
+USE_GITFETCH(NEWTOY(gitfetch, 0, TOYFLAG_USR|TOYFLAG_BIN))
+USE_GITINIT(NEWTOY(gitinit, "<1", TOYFLAG_USR|TOYFLAG_BIN))
+USE_GITREMOTE(NEWTOY(gitremote, "<1", TOYFLAG_USR|TOYFLAG_BIN))
+USE_GPIODETECT(NEWTOY(gpiodetect, ">0", TOYFLAG_USR|TOYFLAG_BIN))
+USE_GREP(NEWTOY(grep, "(line-buffered)(color):;(exclude-dir)*S(exclude)*M(include)*ZzEFHIab(byte-offset)h(no-filename)ino(only-matching)rRsvwc(count)L(files-without-match)l(files-with-matches)q(quiet)(silent)e*f*C#B#A#m#x[!wx][!EF]", TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)|TOYFLAG_LINEBUF))
+USE_GZIP(NEWTOY(gzip, "n(no-name)cdfkt123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_REBOOT(OLDTOY(halt, reboot, TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
+USE_HD(OLDTOY(hd, hexdump, TOYFLAG_USR|TOYFLAG_BIN))
+USE_HEAD(NEWTOY(head, "?n(lines)#<0=10c(bytes)#<0qv[-nc]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
+USE_HWCLOCK(NEWTOY(hwclock, ">0(fast)f(rtc):u(utc)l(localtime)t(systz)s(hctosys)r(show)w(systohc)[-ul][!rtsw]", TOYFLAG_SBIN))
+USE_I2CTRANSFER(NEWTOY(i2ctransfer, "<2vfy", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_INSMOD(NEWTOY(insmod, "<1", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
+USE_IP(OLDTOY(ipaddr, ip, TOYFLAG_SBIN))
+USE_IPCRM(NEWTOY(ipcrm, "m*M*s*S*q*Q*", TOYFLAG_USR|TOYFLAG_BIN))
+USE_IP(OLDTOY(iplink, ip, TOYFLAG_SBIN))
+USE_IP(OLDTOY(iproute, ip, TOYFLAG_SBIN))
+USE_IP(OLDTOY(iprule, ip, TOYFLAG_SBIN))
+USE_IP(OLDTOY(iptunnel, ip, TOYFLAG_SBIN))
+USE_LAST(NEWTOY(last, "f:W", TOYFLAG_BIN))
+USE_LN(NEWTOY(ln, "<1rt:Tvnfs", TOYFLAG_BIN))
+USE_LS(NEWTOY(ls, "(sort):(color):;(full-time)(show-control-chars)\377(block-size)#=1024<1\241(group-directories-first)\376ZgoACFHLNRSUXabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][-Nqb][-k\377]", TOYFLAG_BIN))
+USE_LSATTR(NEWTOY(lsattr, "ldapvR", TOYFLAG_BIN))
+USE_LSMOD(NEWTOY(lsmod, NULL, TOYFLAG_SBIN))
+USE_LSOF(NEWTOY(lsof, "lp*t", TOYFLAG_USR|TOYFLAG_BIN))
+USE_LSPCI(NEWTOY(lspci, "emkn@x@i:", TOYFLAG_USR|TOYFLAG_BIN))
+USE_LSUSB(NEWTOY(lsusb, "i:", TOYFLAG_USR|TOYFLAG_BIN))
+USE_MAKEDEVS(NEWTOY(makedevs, "<1>1d:", TOYFLAG_USR|TOYFLAG_BIN))
+USE_MDEV(NEWTOY(mdev, "s", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_UMASK))
+USE_MKDIR(NEWTOY(mkdir, "<1"USE_MKDIR_Z("Z:")"vp(parent)(parents)m:", TOYFLAG_BIN|TOYFLAG_UMASK))
+USE_MKNOD(NEWTOY(mknod, "<2>4m(mode):"USE_MKNOD_Z("Z:"), TOYFLAG_BIN|TOYFLAG_UMASK))
+USE_MKPASSWD(NEWTOY(mkpasswd, ">2S:m:P#=0<0", TOYFLAG_USR|TOYFLAG_BIN))
+USE_MODINFO(NEWTOY(modinfo, "<1b:k:F:0", TOYFLAG_SBIN))
+USE_MODPROBE(NEWTOY(modprobe, "alrqvsDbd*", TOYFLAG_SBIN))
+USE_NBD_CLIENT(OLDTOY(nbd-client, nbd_client, TOYFLAG_USR|TOYFLAG_BIN))
+USE_NBD_SERVER(OLDTOY(nbd-server, nbd_server, TOYFLAG_USR|TOYFLAG_BIN))
+USE_NETCAT(OLDTOY(nc, netcat, TOYFLAG_USR|TOYFLAG_BIN))
+USE_NETCAT(NEWTOY(netcat, "^tElLw#<1W#<1p#<1>65535q#<1s:f:46uUnvz[!tlL][!Lw][!Lu][!46U]", TOYFLAG_BIN))
+USE_OD(NEWTOY(od, "j#vw#<1=16N#xsodcbA:t*", TOYFLAG_USR|TOYFLAG_BIN))
+USE_PASSWD(NEWTOY(passwd, ">1a:dlu", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
+USE_PASTE(NEWTOY(paste, "d:s", TOYFLAG_USR|TOYFLAG_BIN))
+USE_PGREP(NEWTOY(pgrep, "?cld:u*U*t*s*P*g*G*fnovxL:[-no]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_PING(OLDTOY(ping6, ping, TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
+USE_REBOOT(OLDTOY(poweroff, reboot, TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
+USE_ULIMIT(OLDTOY(prlimit, ulimit, TOYFLAG_USR|TOYFLAG_BIN))
+USE_READAHEAD(NEWTOY(readahead, NULL, TOYFLAG_BIN))
+USE_READLINK(NEWTOY(readlink, "<1vnf(canonicalize)emqz[-mef][-qv]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_RM(NEWTOY(rm, "f(force)iRrv[-fi]", TOYFLAG_BIN))
+USE_RMDIR(NEWTOY(rmdir, "<1(ignore-fail-on-non-empty)p(parents)", TOYFLAG_BIN))
+USE_RMMOD(NEWTOY(rmmod, "<1wf", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
+USE_SED(NEWTOY(sed, "(help)(version)(tarxform)e*f*i:;nErz(null-data)s[+Er]", TOYFLAG_BIN|TOYFLAG_NOHELP))
+USE_SETFATTR(NEWTOY(setfattr, "hn:|v:x:|[!xv]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_SHA1SUM(OLDTOY(sha1sum, md5sum, TOYFLAG_USR|TOYFLAG_BIN))
+USE_SHA224SUM(OLDTOY(sha224sum, md5sum, TOYFLAG_USR|TOYFLAG_BIN))
+USE_SHA256SUM(OLDTOY(sha256sum, md5sum, TOYFLAG_USR|TOYFLAG_BIN))
+USE_SHA384SUM(OLDTOY(sha384sum, md5sum, TOYFLAG_USR|TOYFLAG_BIN))
+USE_SHA512SUM(OLDTOY(sha512sum, md5sum, TOYFLAG_USR|TOYFLAG_BIN))
+USE_SKELETON_ALIAS(NEWTOY(skeleton_alias, "b#dq", TOYFLAG_USR|TOYFLAG_BIN))
+USE_SORT(NEWTOY(sort, USE_SORT_FLOAT("g")"S:T:m" "o:k*t:" "xVbMCcszdfirun", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
+USE_STRACE(NEWTOY(strace, "^p#s#v", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_STRINGS(NEWTOY(strings, "t:an#=4<1fo", TOYFLAG_USR|TOYFLAG_BIN))
+USE_SYSLOGD(NEWTOY(syslogd,">0l#<1>8=8R:b#<0>99=1s#<0=200m#<0>71582787=20O:p:f:a:nSKLD", TOYFLAG_SBIN|TOYFLAG_STAYROOT))
+USE_TAIL(NEWTOY(tail, "?fFs:c(bytes)-n(lines)-[-cn][-fF]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
+USE_TASKSET(NEWTOY(taskset, "<1^pa", TOYFLAG_USR|TOYFLAG_BIN))
+USE_TEE(NEWTOY(tee, "ia", TOYFLAG_USR|TOYFLAG_BIN))
+USE_TELNET(NEWTOY(telnet, "<1>2", TOYFLAG_BIN))
+USE_TELNETD(NEWTOY(telnetd, "w#<0b:p#<0>65535=23f:l:FSKi[!wi]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_SH(OLDTOY(toysh, sh, TOYFLAG_BIN))
+USE_TR(NEWTOY(tr, "^<1>2Ccstd[+cC]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_TRACEROUTE(NEWTOY(traceroute, "<1>2i:f#<1>255=1z#<0>86400=0g*w#<0>86400=5t#<0>255=0s:q#<1>255=3p#<1>65535=33434m#<1>255=30rvndlIUF64", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
+USE_TRACEROUTE(OLDTOY(traceroute6,traceroute, TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
+USE_TRUE(NEWTOY(true, NULL, TOYFLAG_BIN|TOYFLAG_NOHELP|TOYFLAG_MAYFORK))
+USE_TRUNCATE(NEWTOY(truncate, "<1s:|c", TOYFLAG_USR|TOYFLAG_BIN))
+USE_TSORT(NEWTOY(tsort, ">1", TOYFLAG_USR|TOYFLAG_BIN))
+USE_TCPSVD(OLDTOY(udpsvd, tcpsvd, TOYFLAG_USR|TOYFLAG_BIN))
+USE_UNAME(NEWTOY(uname, "paomvrns", TOYFLAG_BIN))
+USE_UNICODE(NEWTOY(unicode, "<1", TOYFLAG_USR|TOYFLAG_BIN))
+USE_USERADD(NEWTOY(useradd, "<1>2u#<0G:s:g:h:SDH", TOYFLAG_NEEDROOT|TOYFLAG_UMASK|TOYFLAG_SBIN))
+USE_UUDECODE(NEWTOY(uudecode, ">1o:", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_UMASK))
+USE_UUENCODE(NEWTOY(uuencode, "<1>2m", TOYFLAG_USR|TOYFLAG_BIN))
+USE_WC(NEWTOY(wc, "Lcmwl", TOYFLAG_USR|TOYFLAG_BIN))
+USE_WHICH(NEWTOY(which, "<1a", TOYFLAG_USR|TOYFLAG_BIN))
+USE_WHOAMI(OLDTOY(whoami, logname, TOYFLAG_USR|TOYFLAG_BIN))
+USE_XARGS(NEWTOY(xargs, "^E:P#<0(null)=1optr(no-run-if-empty)n#<1(max-args)s#0[!0E]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_XZCAT(NEWTOY(xzcat, NULL, TOYFLAG_USR|TOYFLAG_BIN))
+USE_ZCAT(NEWTOY(zcat, "cdfkt123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
diff --git a/scripts/prereq/generated/tags.h b/scripts/prereq/generated/tags.h
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/scripts/prereq/generated/tags.h
@@ -0,0 +1 @@
+
diff --git a/scripts/probes/cmd2dpkg b/scripts/probes/cmd2dpkg
new file mode 100755
index 00000000..6a9c3489
--- /dev/null
+++ b/scripts/probes/cmd2dpkg
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+# Show debian packages host versions of each command live in
+# (Alas, not as useful as I thought it would be.)
+
+[ -x toybox ] || { echo "no ./toybox" >&2; exit 1; }
+
+declare -A ray
+
+# Sad that this is NOT in the default path, but less dumb than /bin/sh->dash
+PATH="$PATH":/sbin:/usr/sbin
+
+# Only checks installed packages, puts anything it can't find in none:
+for i in $(./toybox)
+do
+ tty -s && echo -n . >&2
+ which $i >/dev/null || { ray["none:"]+=" $i"; continue; }
+
+ ray[$(dpkg-query -S $(readlink -f $(which $i)) | toybox cut -DF 1)]+=" $i"
+done
+
+# Print results
+for i in ${!ray[@]}
+do
+ echo $i ${ray[$i]}
+done
diff --git a/scripts/recreate-prereq.sh b/scripts/recreate-prereq.sh
new file mode 100755
index 00000000..ec90f5ac
--- /dev/null
+++ b/scripts/recreate-prereq.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+# Regenerate scripts/prereq (hopefully) portable build.
+
+# Detect toybox prerequisites using record-commands
+
+mkroot/record-commands make clean defconfig toybox
+sed -i 's/default y/default n/' generated/Config.probed
+CMDLIST="$(echo toybox; ./toybox cut -DF 1 log.txt | sort -u | grep -v nproc)"
+{
+ for i in $(tr '[:lower:]' '[:upper:]' <<<"$CMDLIST")
+ do
+ grep -qi CONFIG_$i'[= ]' .config && echo CONFIG_$i=y
+ done
+} > prereq.mini
+
+# Create minimal dependency-free build
+
+make clean allnoconfig KCONFIG_ALLCONFIG=prereq.mini
+make toybox
+cat > scripts/prereq/build.sh << 'EOF'
+#!/bin/sh
+
+BUILD='cc -funsigned-char -I scripts/prereq -I . -Os -ffunction-sections -fdata-sections -fno-asynchronous-unwind-tables -fno-strict-aliasing -DTOYBOX_VERSION=""'
+LINK=''
+EOF
+grep -A999 FILES= generated/build.sh >> scripts/prereq/build.sh
+sed -i 's/ toybox$/&-prereq/' scripts/prereq/build.sh
+
+# harvest stripped down headers
+
+echo > scripts/prereq/generated/tags.h
+sed 's/.*/#define HELP_& ""/' <<<"$CMDLIST" > scripts/prereq/generated/help.h
+egrep "($(xargs <<<"$CMDLIST"|tr ' [:lower:]' '|[:upper:]'))" \
+ generated/newtoys.h > scripts/prereq/generated/newtoys.h
+FORS="$(sed -n 's/#define FOR_//p' $(grep -o 'toys/[^/]*/[^.]*\.c' scripts/prereq/build.sh) | xargs | tr ' ' '|')"
+sed -En '1,/^$/p;/\/\/ ('"$FORS"') /,/^$/p;/#ifdef FOR_('"$FORS"')$/,/^$/p' generated/flags.h > scripts/prereq/generated/flags.h
+egrep "OPTSTR_($(egrep -v "($FORS)" <<<"$CMDLIST" | xargs | tr ' ' '|'))" \
+ generated/flags.h >> scripts/prereq/generated/flags.h
+# TODO: slim down config.h
+cp generated/{globals,config}.h scripts/prereq/generated/
diff --git a/tests/fold.test b/tests/fold.test
index 80c7fd3c..80c7fd3c 100644..100755
--- a/tests/fold.test
+++ b/tests/fold.test
diff --git a/tests/timeout.test b/tests/timeout.test
index 694540ae..624f3650 100755
--- a/tests/timeout.test
+++ b/tests/timeout.test
@@ -8,13 +8,13 @@
testcmd "times out" '.1 sleep 100 ; echo $?' '124\n' '' ''
testcmd "failure" '-s MONKEY .1 sleep 100 2>/dev/null ; echo $?' '125\n' '' ''
testcmd "early failure" '2>/dev/null ; echo $?' '125\n' '' ''
-testcmd "can't execute" '.1 / 2>/dev/null ; echo $?' '126\n' '' ''
-testcmd "can't find" '.1 /does/not/exist 2>/dev/null ; echo $?' '127\n' '' ''
+testcmd "can't execute" '1 / 2>/dev/null ; echo $?' '126\n' '' ''
+testcmd "can't find" '1 /does/not/exist 2>/dev/null ; echo $?' '127\n' '' ''
testcmd "custom signal" '-s 3 .1 sleep 100; echo $?' '124\n' '' ''
testcmd "killed" '-s 9 .1 sleep 100; echo $?' '137\n' '' ''
testcmd "TERM" '-s TERM .1 sleep 100; echo $?' '124\n' '' ''
-testcmd "exit 0" '.1 true ; echo $?' '0\n' '' ''
-testcmd "exit 1" '.1 false ; echo $?' '1\n' '' ''
+testcmd "exit 0" '1 true ; echo $?' '0\n' '' ''
+testcmd "exit 1" '1 false ; echo $?' '1\n' '' ''
testcmd "--preserve-status" '--preserve-status .1 sleep 100 ; echo $?' '143\n' '' ''
testcmd "--preserve-status killed" '--preserve-status -s 9 .1 sleep 100 ; echo $?' '137\n' '' ''
diff --git a/tests/touch.test b/tests/touch.test
index 6d131d7c..6d131d7c 100644..100755
--- a/tests/touch.test
+++ b/tests/touch.test
diff --git a/toys.h b/toys.h
index 88b7a837..94d0c4b5 100644
--- a/toys.h
+++ b/toys.h
@@ -141,5 +141,5 @@ extern char **environ, *toybox_version, toybuf[4096], libbuf[4096];
#ifndef TOYBOX_VENDOR
#define TOYBOX_VENDOR ""
#endif
-#define TOYBOX_VERSION "0.8.10"TOYBOX_VENDOR
+#define TOYBOX_VERSION "0.8.11"TOYBOX_VENDOR
#endif
diff --git a/toys/other/inotifyd.c b/toys/other/inotifyd.c
index 3dc66025..4e886bc5 100644
--- a/toys/other/inotifyd.c
+++ b/toys/other/inotifyd.c
@@ -5,7 +5,7 @@
*
* No Standard.
-USE_INOTIFYD(NEWTOY(inotifyd, "<2", TOYFLAG_USR|TOYFLAG_BIN))
+USE_INOTIFYD(NEWTOY(inotifyd, "<2", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
config INOTIFYD
bool "inotifyd"
@@ -55,7 +55,6 @@ void inotifyd_main(void)
if (!masks) mask = 0xfff; // default to all
else{
- *masks++ = 0;
for (*masks++ = 0; *masks; masks++) {
i = stridx(masklist, *masks);;
if (i == -1) error_exit("bad mask '%c'", *masks);
diff --git a/toys/other/watch.c b/toys/other/watch.c
index 995aae15..a47aa3c2 100644
--- a/toys/other/watch.c
+++ b/toys/other/watch.c
@@ -1,4 +1,4 @@
-/* watch.c - Execute a program periodically
+/* watch.c - Show bounded output of a periodically executed command.
*
* Copyright 2013 Sandeep Sharma <sandeep.jack2756@gmail.com>
* Copyright 2013 Kyungwan Han <asura321@gmail.com>
@@ -6,21 +6,22 @@
* No standard. See http://man7.org/linux/man-pages/man1/watch.1.html
*
* TODO: trailing combining characters
+
USE_WATCH(NEWTOY(watch, "^<1n%<100=2000tebx", TOYFLAG_USR|TOYFLAG_BIN))
config WATCH
bool "watch"
default y
help
- usage: watch [-tebx] [-n SEC] PROG ARGS
+ usage: watch [-tebx] [-n SEC] COMMAND...
- Run PROG every -n seconds, showing output. Hit q to quit.
+ Run COMMAND every -n seconds, showing output that fits terminal, q to quit.
- -n Loop period in seconds (default 2)
+ -n Number of seconds between repeats (default 2.0)
-t Don't print header
-e Exit on error
-b Beep on command error
- -x Exec command directly (vs "sh -c")
+ -x Exec command directly (without "sh -c")
*/
#define FOR_watch
@@ -57,7 +58,7 @@ static void watch_child(int sig)
static int watch_escape(FILE *out, int cols, int wc)
{
if (wc==27 || (wc>=7 && wc<=13)) return -1;
- if (wc < 32) return 0;
+ if (wc<32) return 0;
return crunch_escape(out, cols, wc);
}
@@ -88,13 +89,12 @@ void watch_main(void)
xsignal_flags(SIGCHLD, watch_child, SA_RESTART|SA_NOCLDSTOP);
for (;;) {
- fflush(NULL);
+ fflush(0);
// Time for a new period?
if ((now = millitime())>=then) {
-
// Incrementing then instead of adding offset to now avoids drift,
- // loop is in case we got suspend/resumed and need to skip periods
+ // loop in case we got suspend/resumed and need to skip periods
while ((then += TT.n)<=now);
start_redraw(&width, &height);
@@ -112,7 +112,7 @@ void watch_main(void)
if (pad>0) draw_trim(cmd, -pad, pad);
printf("%c", pad<cmdlen ? '*' : ' ');
if (width) xputs(ss+(width>ctimelen ? 0 : width-1));
- if (yy>=3) xprintf("\r\n");
+ if (height>=3) xprintf("\r\n");
xx = 0;
yy = 2;
}
diff --git a/www/faq.html b/www/faq.html
index 84cf3107..c39ae274 100644
--- a/www/faq.html
+++ b/www/faq.html
@@ -826,7 +826,7 @@ should list all the available cross compilers it recognizes under ccc,
something like:</p>
<blockquote><b><p>
-aarch64 armv4l armv5l armv7l armv7m armv7r i486 i686 m68k microblaze mips mips64 mipsel or1k powerpc powerpc64 powerpc64le s390x sh2eb sh4 x32 x86_64
+aarch64 armv4l armv5l armv7l armv7m armv7r i486 i686 m68k microblaze mips mips64 mipsel or1k powerpc powerpc64 powerpc64le riscv32 riscv64 s390x sh2eb sh4 sh4eb x32 x86_64
</p></b></blockquote>
<p>(A long time ago I
diff --git a/www/header.html b/www/header.html
index e72481f4..ec0d2969 100644
--- a/www/header.html
+++ b/www/header.html
@@ -55,5 +55,5 @@
</td>
<td valign=top>
-<h2>Current release <a href=https://landley.net/toybox/news.html>0.8.10</a> (July 30, 2023)</a></h2>
+<h2>Current release <a href=https://landley.net/toybox/news.html>0.8.11</a> (April 8, 2024)</a></h2>
<hr>
diff --git a/www/news.html b/www/news.html
index f983d6f3..8054c635 100644
--- a/www/news.html
+++ b/www/news.html
@@ -37,6 +37,304 @@ bootable under QEMU (built using a <a href=https://github.com/landley/linux/tree
<u>Build</u>:
-->
+<a name="08-04-2024" /><a href="#08-04-2024"><hr><h2><b>April 8, 2024</b></h2></a>
+<blockquote>
+<p>Another thing that got forgotten was the fact that against all probability a
+sperm whale had suddenly been called into existence several miles above the
+surface of an alien planet. And since this is not a naturally tenable position
+for a whale, this poor innocent creature had very little time to come to terms
+with its identity as a whale before it then had to come to terms with not being
+a whale any more.</p>
+<p>- The Hitchhiker's Guide to the Galaxy</p>
+</blockquote>
+
+<p><a href=downloads/toybox-0.8.11.tar.gz>Toybox 0.8.11</a>
+(<a href=https://github.com/landley/toybox/releases/tag/0.8.11>git commit</a>)
+is out, with prebuilt <a href=/bin/toybox/0.8.11>static binaries</a> and
+<a href=/bin/mkroot/0.8.11>mkroot images</a>
+bootable under QEMU (built using a <a href=/bin/mkroot/0.8.11/linux-patches>lightly patched</a> linux-6.8).</p>
+
+<p>Highlights include a new <a href=quickstart.html>quickstart</a>
+web page, shorter <a href=/bin>/bin</a> links to prebuilt binaries,
+lots of work on mkroot, and a new "canned" toybox build to reduce
+dependencies.</p>
+
+<p><u>New commands</u>:
+Rob added <b>tsort</b>, and promoted <b>fold</b> and <b>getopt</b>.
+Oliver Webb added <b>ts</b> and <b>csplit</b>, and
+Elliott added <b>memeater</b>.</p>
+
+<p>And one command got temporarily de-promoted: <b>passwd</b> is "default n"
+(disabled in defconfig) this release due to the ongoing lib/passwd.c
+infrastructure rewrite that isn't quite done yet. (See the Library section.)</p>
+
+<u>Features</u>:
+The new "<a href=https://github.com/landley/toybox/commit/d1acc6e88be5>canned</a>"
+toybox build in <b>scripts/prereq/build.sh</b> lets toybox provide its own
+build prerequisites by compiling a minimal toybox against saved headers (ala
+"cc -I scripts/prereq/generated file1.c file2.c..."). This provides
+most of the commands toybox needs to configure and build itself (except make,
+bash, and the compiler toolchain). This may help <a href=https://github.com/landley/toybox/commit/3bbc31c78b41>bootstrap</a> toybox on systems
+that don't provide a modern Linux command line out of the box: install
+toybox-prereq at the start of the $PATH, add
+a .config file, and run <b>scripts/make.sh</b>.</p>
+
+<p>New <b>mv -x</b> option to atomically swap two files,
+<b>env -e FILE</b> executes a different command than argv[0] on the command
+line, the <b>reset</b> command now puts raw terminals back into "cooked" mode,
+negative offsets in <b>sort -k</b> count right to left,
+<b>setsid</b> grabs the tty more forcefully (removing the need for getty)
+and the -cc option will try to steal it,
+<b>mount</b> now shows file= when displaying loopback mounts,
+<b>wc -L</b> shows longest line length,
+<b>tar -h</b> now detects a lot more hardlinks,
+<b>cp</b> now copies xattrs for directories (not just files).</p>
+
+<p>Elliott taught <b>file</b> to recognize wasm binary modules and
+display JPEG width/height, added the LOWER_UP, DORMANT, and ECHO
+flags to <b>ifconfig</b>, added PAC and BTI decoding to <b>readelf</b>,
+cache size querying to <b>sysconf</b> (supported by glibc and bionic but
+not musl-libc), and added a "paste" menu to <b>microcom</b>. Kalesh Singh
+taught <b>readelf</b> to decode a new note type (NT_ANDROID_TYPE_PAD_SEGMENT).
+Christopher Ferris improved <b>readelf</b> section flags handling,
+with test. Oliver Webb suggested <b>count -l</b>.
+Aditya submitted <b>netcat -z</b>.</p>
+
+<u>Bugfixes</u>:
+Fixed <b>printf \0</b> and <b>grep -w</b> (which never quite worked right),
+<b>ls -k</b> now switches off --block-size,
+<b>install -dm 02750</b> works (sticky bit support for -d),
+<b>tar</b> is better at following symlinks and extracting records with broken
+metadata, <b>gzip</b> now knows
+knows how to rename between "tgz/tar" extensions,
+<b>mkpasswd -m sha*</b> salt length can now range from 8-16, not just 16,
+<b>ps</b> can now handle an session ID of 0 (which is what PID 1 starts with
+before the first call to setsid()),
+<b>pwgen</b> can now use ~ in output,
+<b>xargs</b> now stops when a child exits with 255,
+<b>iconv</b> now exits with error if any characters failed to convert with -c,
+things like <b>truncate -s 1e2</b> were saying "too large" and now correctly
+say "not integer" (it's not scientific notation, it's exabyte suffix with
+trailing garbage),
+<b>timeout</b> now takes its exit code from SIGCHLD instead of wait()
+to fix a race condition (SIGCHLD can happen before calling wait and the
+kernel won't deliver status twice, so you can't wait AND have the
+signal handler). The usual round of gcc warnings got tracked down, confirmed
+to be useless, and removed, but despite gcc constantly warning "variable is
+not actually used uninitialized" there were some uninitialized variables in
+<b>dd</b> it DIDN'T warn about: found and fixed.</p>
+
+<p>Elliott added an error message to catch <b>xxd -r</b> receiving -p format
+input without -p,
+fixed <b>readelf -n</b> for x86-64 ibt/shstk notes
+(<a href=https://github.com/landley/toybox/commit/6c23ff0168c1>whatever those
+are</a>),
+and fixed <b>blkid</b> not to check filesystem signatures that would continue
+past the end of the loaded buffer.
+Michael Shavit pointed out that <b>devmem</b> command line number parsing
+wasn't unsigned (although fixing that means it no longer parses the kmg unit
+suffixes).
+Peter Collingbourne fixed <b>inotifyd</b> skipping the first mask character.
+Taisuke Matsushiro fixed a fencepost error preventing <b>stty</b> from
+setting serial baud rate to 57600.
+Askar Safin fixed a typo in mkroot/packages/busybox.</p>
+
+<u>Library</u>:
+The in-progress rewrite of <b>lib/password.c</b> no longer uses shadow.h
+(which lets it build against bionic),
+and a new <b>lib/hash.c</b> where toybox implements its own crypt() using
+the md5/sha1/sha3 etc hash functions we've already got (to work around glibc's
+ongoing deprecation of posix features), but neither are quite finished yet.
+New <b>lib/elf.c</b> with plumbing shared by <b>file</b> and <b>readelf</b>, with
+additional arm and riscv flag decoding,
+the <b>peek()</b> family of functions now return long long instead of
+int64_t so the base types are consistent on 32/64 bit,
+<b>lib/args.c</b> now handles the high bit octal escape sequences in trailing
+[-abc] blocks, so you can have punctuation participate in option groups,
+switching off an option via grouping now sets it back to its default
+value (not to zero), and numeric and date parsing report out of range numeric
+or millisecond values.</p>
+
+<u>Mkroot</u>:
+There's a <b>README</b> in the mkroot directory now. (Microsoft Github was
+picking up the README.root file used by the tar-for-web.sh script
+and showing that instead.)
+Extended <b>run-qemu.sh</b> so it can be run from other directories
+(prepending $(dirname $0)/ to linux-kernel and initramfs.cpio.gz when
+loading them into qemu).
+The initramfs now has <b>/etc/os-release</b> with the toybox $VERSION.
+The big if/else staircase of linux kernel target configurations
+moved into its own <b>get_target_config()</b> shell function, with
+a big comment block right before it explaining what all the variables
+it sets mean, and the generic kconfig symbol list got moved out to
+a <b>GENERIC_KCONF</b> variable assignment right after that function.
+The <b>microconfig</b> format got compressed slightly more
+by use of bash brace expansion, decoded to comma separated values by
+the be2csv function ala KCONF="$(be2csv SPI{,_BITBANG} IOMMU_SUPPORT)" .
+The init script no longer calls <b>oneit</b>, instead doing the work in the
+init script. (Redirect stdin/out/err to the "real" console device on
+the last line of /sys/class/tty/console/active, call setsid, trap SIGCHLD,
+reboot when the shell exits. This (and the setsid tty stealing upgrades) also
+fixed <b>ps</b> not showing any processes in mkroot because stdin/stdout weren't
+properly claimed as the controlling tty.
+The base kernel config now uses <b>CONFIG_PANIC_TIMEOUT=1</b> so
+we don't have to say panic=1 on the kernel command line anymore.
+The baseconfig now automatically adds CONFIG_MODULES and
+CONFIG_MODULES_UNLOAD when any <b>$MODULES</b> are listed.
+Moved the kernel modules archive into the "docs" directory.
+New <b>$NOTOYBOX</b> variable skips the toybox build if set.
+The <b>$DTB</b> files no longer have a path, instead using "find"
+to install them.
+The build now creates the externally loadable cpio.gz file even when
+building initramfs into the kernel, but sticks it in the docs/ subdirectory
+when it's not used.</p>
+
+<p>Several new <b>mcm-buildall.sh</b> targets (or1k, riscv32, riscv64, sh4eb)
+taking advantage of upstream musl-cross-make updating itself to use
+musl-1.2.5. The target list in mcm-buildall.sh moved into a <b>TARGETS=()</b>
+array with a big comment before it explaining the format, and the script
+is better about building host toolchains
+to build other cross compilers with: it tries to autodetect the host
+type (moving the relevant one to the front of the build list), and
+will also build a missing host toolchain when given targets on the
+command line. Added microblaze and or1k kernel configs, neither of which
+know how to exit qemu yet. (If Linux has got a reboot mechanism it knows
+how to poke that qemu is listening for on either virtual board, I haven't
+found it yet.) Also added sh4eb with FDPIC support (see kernel patch, which
+allows qemu-system-sh4eb to run the sh2eb nommu root filesystem), and armv4l
+(the 486 of arm).</p>
+
+<u>Pending</u>:
+Elliott fixed and improved <b>strace</b>, translating more system calls.
+Rob enabled command recursion in <b>toysh</b> (so it can call non-builtins as
+builtins), fixed calling "exec" on NOFORK commands (which MUST run
+in the shell's process context), redid the code to handle trailing
+backslashes gluing lines together, and it no longer leaks script
+filehandles into child processes.
+Oliver Webb noticed that OLDTOY(MAYFORK) aliases didn't become shell
+builtins, added <b>tr -t</b>, in <b>vi</b> added line gotos in ex mode,
+'g', 'v', 'j' commands, and backwards search, cleaned up stuff in
+<b>xzcat</b>, <b>getopt</b>, <b>bc</b>, and removed a bunch of useless autogenerated
+<b>bc</b> tests. Jarno Mäkipää added the list of supported commands to <b>vi</b>'s
+help text.
+Mathieu Anquetin fixed <b>ip link set</b> parsing, and NUL byte handling
+in <b>hexdump</b>.
+General cleanup passes on <b>expr</b> (which now uses 64 bit comparisons),
+<b>tr</b>, and <b>dhcpd</b>.</p>
+
+<u>Cleanup</u>:
+pass over <b>lsattr</b>, <b>getconf</b>, <b>acpi</b>, and <b>blkid</b>.
+Use FLAG() macros in <b>ifconfig</b> and <b>restorecon</b>. Removed TODO block
+from <b>nbd-client</b>.
+More error_msg("%s", str) converted to error_msg_raw(str).
+Trimmed the GLOBALS() sizes (using <b>scripts/probes/GLOBALS</b>):
+removed 1k of global data from <b>cksum</b> and switched a 2k global
+in <b>grep</b> to a malloc. Simplified scripts/probes/bloatcheck and
+mkroot/record-commands.</p>
+
+<u>Portability</u>:
+Fixed <b>truncate -s 8g</b> on 32 bit hosts,
+updated <b>mcm-buildall.sh</b> to autodetect host type and automatically
+select newer package versions,
+and moved the <b>linux32</b> command to its own file because BSD can't
+build it.
+MacOS had a use-after-free with the getpwuid() return value being recycled
+a more aggressively than Linux.
+Elliott fixed diff.test to work with mksh, and posix_fallocate()
+to work with MacOS.
+More commands enabled in <b>make bsd_defconfig</b> and <b>make
+macos_defconfig</b>.
+Added some (void) typecasts to netstat, oneit, and watchdog to try to
+shut up compilers that insist on responding to uncorrectable failures.
+(Such as fgets() reading known /proc data from the kernel, writes to
+the watchdog timer that will reboot the system if they fail, or PID 1 calling
+dup() on stdin to create stdout and stderr after closing the old ones.
+If any of that goes wrong, what are we supposed to do about it?)</p>
+
+<u>Documentation</u>:
+The website now has a <a href=quick.html>quickstart</a> page,
+and the site now defaults to the about page (updated index.html symlink).
+The "current release" is now in the common header displayed by most pages.
+The mkroot dir has a
+<a href=https://github.com/landley/toybox/blob/0.8.11/mkroot/README>README</a>, and its <a href=faq.html#mkroot>faq entry</a>
+has been updated.
+New option to compress help text with <b>gzip</b>, and help text size now shows
+up in <b>make bloatcheck</b>.
+Fix <b>sed --help</b> to show full help, <b>patch -F</b> is now mentioned
+in the help text, tweaks to help text in <b>cut</b>, <b>grep</b>,
+<b>blkdiscard</b>.
+Elliott did a cleanup pass over "usage:" lines and alphabetized more help text
+options.
+Christian Koestlin fixed a typo in the <b>dmesg</b> docs.
+The <a href=release.txt>release
+procedure checklist</a> has been updated, and the README generated
+by <b>mkroot/tar-for-web.sh</b> got updated.
+New faq entry explaining why toybox doesn't have (or need) cttyhack,
+and the architecture list got updated to match mcm-buildall.sh.
+The usual roadmap updates.</p>
+
+<p>New <b>scripts/probes/cmd2dpkg</b> script shows what
+debian package (if any) each toybox command lives in, but only checks
+installed packages (dpkg-query -S "$(which $COMMAND)") and debian breaks
+up source packages strangely, so did not used it to redo the roadmap section
+listing packages (created using Linux From Scratch's list of commands
+installed by each source package).</p>
+
+<u>Plumbing</u>:
+The <b>yes</b> command now uses writev() to go way faster, mostly to
+prove it can.
+The default <b>stdout</b> buffer type switched to block buffering to make
+Elliott happy, which is a rich source of bugs (many of which Elliott
+has already whack-a-moled) and means among other things
+that mixing write() and fwrite() calls now requires manual flushing.
+Meanwhile xflush() became xferror() because it usually
+wasn't flushing anyway, and now that's more noticeable.
+Removed <b>TOYFLAG_LOCALE</b> and just set utf8 locale for all commands.
+The dirtree code now sets <b>DIRTREE_SYMFOLLOW</b> in "again" when we followed
+a symlink to get to this node, callers checking <b>DIRTREE_COMEAGAIN</b> need
+to mask out the bit they're interested in.
+Improved <b>scripts/probes/findglobals</b> output to be more legible.</p>
+
+<u>Test suite</u>:
+Added <b>make test_help test_install</b> targets. (The standalone
+command targets conflict with the help/install make targets, but you
+can still build them via scripts/single.sh and there's no reason not
+to be able to individually test them.)
+New <b>utf8locale</b> shell function attempts to enable a UTF8 locale for
+TEST_HOST, which was used to fix <b>wc.test</b>.
+Colin Cross fixed <b>pidof.test</b> when stdout is a socket.
+Something called "ecryptfs" has a maximum filename length of 143 bytes,
+so our <b>tar.test</b> for long filenames support needs to be skipped there
+because the filesystem can't handle it. Similarly, our <b>truncate.test</b>
+was failing because storing nothing on ecryptfs wasts more space than expected.
+The <b>tar</b> tests now fetch user/group names with "stat" because
+between Linux, Android, FreeBSD, and MacOS, there aren't really consistent
+user and group names for any existing files. Added nbd-client.test
+Thiébaud Weksteen fixed the <b>getfattr</b>/<b>setfattr</b> tests on
+filesystems using selinux. Oliver Webb added <b>sha3sum</b> tests.
+Elliott stabilized another slightly racy <b>ifconfig</b> test (big test
+farm, hits the weird corner cases).</p>
+
+<u>Build</u>:
+Lots of changes to <b>scripts/make.sh</b> and friends to speed up and parallelize
+header generation. The build now figures out which toys/*/*.c files
+to compile by searching for unindented USE() macros wrapping NEW(commandname),
+which among other things fixes enabling the builtins when selecting just
+CONFIG_SH in menuconfig (instead of doing a "make sh" single command build).
+It also probes for optional shared libraries in parallel.
+New <b>scripts/probes</b> directory to collect scripts that aren't actually
+used by the build, with a README in it.
+Updated .gitignore so it doesn't complain about spurious name collisions in
+subdirectories. Elliott shut up a
+<a href=https://github.com/landley/toybox/commit/2c36636377e1>truly sad</a>
+warning where despite sizeof(ptrdiff_t) always being sizeof(long), gcc
+nevertheless warns if you printf("%ld", ptr-ptr) and wants a magic invented
+"%td" type on 32 bit systems (but is just fine on 64 bit). (Or we could add a
+literally NOP typecast to long.) And silenced a spurious gcc 13.2 warning
+in date.c. And Rob shut up <a href=https://github.com/landley/toybox/commit/a17fee778851>more broken gcc warnings</a>.
+Updated .gitignore so it doesn't complain about spurious name collisions in
+subdirectories.</p>
+
<a name="30-07-2023" /><a href="#30-07-2023"><hr><h2><b>July 30, 2023</b></h2></a>
<blockquote>
<p>The way it functioned was very interesting. When the Drink button was
diff --git a/www/roadmap.html b/www/roadmap.html
index 79a44089..78b1729b 100644
--- a/www/roadmap.html
+++ b/www/roadmap.html
@@ -20,6 +20,7 @@
<a href=#sash>sash</a>, <a href=#sbase>sbase</a>,
<a href=#uclinux>uclinux</a>...</li>
<li><a href=#packages>Other Packages</a></li>
+<li><a href=#todo>TODO list</a></li>
</ul>
<a name="goals" />
@@ -34,7 +35,7 @@ commplation.</p>
<p>The most interesting publicly available standards are A) POSIX-2008 (also
known as SUSv4), B) the Linux Standard Base version 4.1, and C) the official
<a href=https://www.kernel.org/doc/man-pages/>Linux man pages</a>.
-But they include commands we've decided not implement, exclude
+But each of those include commands we've decided not implement, exclude
commands or features we have, and don't always entirely match reality.</p>
<p>The most thorough real world test (other than a large interactive
@@ -48,19 +49,17 @@ plus <a href=faq.html#cross>musl-cross-make</a> to hermetically build
<a href=https://source.android.com>AOSP</a>.</p>
<p>We've also checked what commands were provided by similar projects
-(klibc, sash, sbase, embutils,
-nash, and beastiebox), looked at various vendor configurations of busybox,
-and collected end user requests.</p>
+(klibc, sash, sbase, embutils, nash, beastiebox...), looked at various
+vendor configurations of busybox, and collected end user requests.</p>
<p>Finally, we'd like to provide a good replacement for the Bash shell,
-which was the first program Linux ever ran and remains the standard shell
-of Linux (no matter what Ubuntu says). This doesn't necessarily mean including
-every last Bash 5.x feature, but does involve {various,features} &lt(beyond)
-posix.</p>
+which was the first program Linux ever ran (leading up to the 0.0.1 release
+in 1991) and remains the standard shell of Linux (no matter what Ubuntu says).
+This doesn't necessarily mean including every last Bash 5.x feature, but
+does involve {various,features} &lt(beyond) posix.</p>
<p>See the <a href=status.html>status page</a> for the categorized command list
-and progress towards implementing it. There's also a
-<a href=todo.html>historical todo list</a> from the project's 2011 relaunch.</p>
+and progress towards implementing it.</p>
<hr />
<a name="standards">
@@ -68,22 +67,30 @@ and progress towards implementing it. There's also a
<h3><a name=susv4 /><a href="#susv4">POSIX-2008/SUSv4</a></h3>
<p>The best standards describe reality rather than attempting to impose a
-new one. A good standard should document, not legislate.
+new one. I.E. "A good standard should document, not legislate."
Standards which document existing reality tend to be approved by
-more than one standards body, such ANSI and ISO both approving <a href=https://landley.net/c99-draft.html>C99</a>. That's why IEEE 1003.1-2008,
+more than one standards body, such as ANSI and ISO both approving <a href=https://landley.net/c99-draft.html>C99</a>. That's why IEEE 1003.1-2008,
the Single Unix Specification version 4, and the Open Group Base Specification
-edition 7 are all the same standard from three sources, but most people just
-call it "posix" (portable operating system derived from unix).
+edition 7 are all the same standard from three sources, which most people just
+call "posix" (short for "portable operating system that works like unix").
It's available <a href=https://pubs.opengroup.org/onlinepubs/9699919799>online in full</a>, and may be downloaded as a tarball.
Previous versions (<a href=https://pubs.opengroup.org/onlinepubs/009695399/>SUSv3</a> and
<a href=https://pubs.opengroup.org/onlinepubs/7990989775/>SUSv2</a>)
-are also available.
-(Note:
+are also available.</p>
+
+<p>The original Posix was a collection of different standards (POSIX.1
+from 1988, POSIX.1b from 1993, and POSIX.1c from 1995). The unified
+SUSv2 came out in 1997 and SUSv3 came out in 2001.
<a href=https://pubs.opengroup.org/onlinepubs/9699919799.2008edition/>Posix
-2008</a> was reissued in 2013 and 2018, the first was minor wordsmithing
+2008</a> was then reissued in 2013 and 2018, the first was minor wordsmithing
with no behavioral changes, the second was to renew a ten year timeout
-to still be considered a "current standard" by some government regulations.
-It's still posix-2008/SUSv4/issue 7.)</p>
+to still be considered a "current standard" by some government regulations,
+but isn't officially a new standard. It's still posix-2008/SUSv4/Issue 7.
+The endless committee process to produce
+"Issue 8" has been ongoing for over 15 years now, with conference
+calls on mondays and thursdays, mostly to discuss recent bug tracker
+entries then publish the minutes of the meeting on the mailing list.
+Prominent committee members have died during this time.</p>
<h3>Why not just use posix for everything?</h3>
@@ -116,7 +123,7 @@ versions of the standard have been removed, while obsolete commands like
cksum, compress, sccs and uucp remain with no mention of modern counterparts
like crc32/sha1sum, gzip/xz, svn/git or scp/rsync. Meanwhile posix' description
of the commands
-themselves are missing dozens of features and specify silly things like ebcdic
+themselves are missing dozens of features, and specify silly things like ebcdic
support in dd or that wc should use %d (not %lld) for byte counts. So
we have to extensively filter posix to get a useful set of recommendations.</p>
@@ -131,7 +138,7 @@ val what), fortran support (asa fort77), and batch processing support (batch
qalter qdel qhold qmove qmsg qrerun qrls qselect qsig qstat qsub).</p>
<p>Some commands are for a compiler toolchain (ar c99 cflow ctags cxref gencat
-iconv lex m4 make nm strings strip tsort yacc) which is out of scope for
+iconv lex m4 make nm strings strip yacc) which is out of scope for
toybox and should be supplied externally. (Some of these might be
revisited later, but not for toybox 1.0.)</p>
@@ -141,7 +148,7 @@ type ulimit umask unalias wait). These may be implemented as part of the
built-in toybox shell, but are not exported into $PATH via symlinks and
thus are not part of toybox's main command list. (If you fork a
child process and have it "cd" then exit, you've accomplished nothing.)
-Again, what posix provides is incomplete: a shell also needs exit, if, while,
+Again, what posix lists as "commands" is incomplete: a shell also needs exit, if, while,
for, case, export, set, unset, trap, exec... (And for bash compatibility
function, source, declare...)</p>
@@ -167,7 +174,7 @@ csplit cut date dd df diff dirname du echo env expand expr false file find
fold fuser getconf grep head id join kill link ln logger logname ls man
mkdir mkfifo more mv newgrp nice nl nohup od paste patch printf ps
pwd renice rm rmdir sed sh sleep sort split stty tabs tail tee test time
-touch tput tr true tty uname unexpand uniq unlink uudecode uuencode vi wc
+touch tput tr true tsort tty uname unexpand uniq unlink uudecode uuencode vi wc
who xargs zcat
</span>
</b></blockquote>
@@ -182,11 +189,11 @@ being consumed by <a href=https://landley.net/notes-2010.html#18-07-2010>the Lin
<p>Where POSIX allowed its standards process to be compromised
by leaving things out (but what
they DID standardize tends to be respected, if sometimes obsolete),
-the Linux Standard Base's failure mode is different. They respond to
-pressure by including anything their members pay them enough to promote,
+the Linux Standard Base's failure mode was different. They responded to
+pressure by including anything their members paid them enough to promote,
such as allowing Red Hat to push
RPM into the standard even though all sorts of distros (Debian, Slackware, Arch,
-Gentoo, Android) don't use it and never will. This means anything in the LSB is
+Gentoo, Android, Alpine...) don't use it and never will. This means anything in the LSB is
at best a suggestion: arbitrary portions of this standard are widely
ignored.</p>
@@ -199,19 +206,20 @@ of those donors</a> regardless of technical merit. (The Linux Foundation, which
maintains the LSB, is NOT a 501c3. It's a 501c6, the
same kind of legal entity as the Tobacco Institute and
<a href=https://lwn.net/Articles/706585/>Microsoft's</a>
-old "<a href=https://en.wikipedia.org/wiki/Don%27t_Copy_That_Floppy>Don't Copy That Floppy</a>" program.) Debian officially
+old "<a href=https://en.wikipedia.org/wiki/Don%27t_Copy_That_Floppy>Don't Copy That Floppy</a>" campaign.) Debian officially
<a href=http://lwn.net/Articles/658809>washed its hands of LSB</a> by
refusing to adopt release 5.0 in 2015, and no longer even pretends to support
it (which affects Debian derivatives like Ubuntu and Knoppix). Toybox has
-stayed on 4.1 for similar reasons: a lot of historical effort went into
-producing the standard before the Linux Foundation took over.</p>
+stayed on 4.1 for similar reasons.</p>
<p>That said, Posix by itself isn't enough, and this is the next most
-comprehensive standards effort for Linux so far, so we salvage what we can.</p>
+comprehensive standards effort for Linux so far, so we salvage what we can.
+A lot of historical effort went into producing the standard before the
+Linux Foundation took over.</p>
<h3>Analysis</h3>
-<p>The LSB specifies a <a href=http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/cmdbehav.html>list of command line
+<p>LSB 4.1 specifies a <a href=http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/cmdbehav.html>list of command line
utilities</a>:</p>
<blockquote><b>
@@ -223,8 +231,8 @@ patch pidof remove_initd renice sed sendmail seq sh shutdown su sync
tar umount useradd userdel usermod xargs zcat
</b></blockquote>
-<p>Where posix specifies one of those commands, LSB's deltas tend to be
-accomodations for broken tool versions which aren't up to date with the
+<p>Where posix specifies one of those commands, LSB's deltas tended to be
+accomodations for broken tool versions which ween't up to date with the
standard yet. (See <a href=http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/more.html>more</a> and <a href=http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/xargs.html>xargs</a>
for examples.)</p>
@@ -234,7 +242,7 @@ various legacy tool implementations "compliant", this means we're mostly
interested in the set of LSB tools that aren't mentioned in posix.</p>
<p>Of these, gettext and msgfmt are internationalization, install_initd and
-remove_initd weren't present in Ubuntu 10.04, lpr is out of scope,
+remove_initd weren't present even in Ubuntu 10.04, lpr is out of scope,
lsb_release just reports information in /etc/os-release, and sendmail's
turned into a pile of cryptographic verification and DNS shenanigans due
to spammers.</p>
@@ -252,12 +260,13 @@ su sync tar umount useradd userdel usermod zcat
<h3><a name=rfc /><a href="#rfc">IETF RFCs and Man Pages</a></h3>
-<p>They're very nice, but there's thousands of them.</p>
+<p>They're very nice, but there's thousands of them. The signal to noise
+ratio here is terrible.</p>
<p>Discussion of standards wouldn't be complete without the Internet
Engineering Task Force's "<a href=https://www.rfc-editor.org/in-notes/rfc-index.txt>Request For Comments</a>" collection and Michael Kerrisk's
-<a href=https://www.kernel.org/doc/man-pages/>Linux man-pages project</a>.
-Except these aren't standards, they're collections of documentation with
+<a href=https://www.kernel.org/doc/man-pages/>Linux man-pages project</a>...
+except these aren't standards, they're collections of documentation with
low barriers to inclusion. They're not saying "you should support
X", they're saying "if you do, here's how".
Thus neither really helps us select which commands to include.</p>
@@ -275,13 +284,14 @@ the result. As with man pages they can be <a href=https://www.ietf.org/rfc/rfc06
<a href=https://www.ietf.org/rfc/rfc1951.txt>terse and impenetrable</a>,
have developed a certain amount of <a href=https://www.ietf.org/rfc/rfc8179.txt>bureaucracy</a> over the years, and often the easiest way to understand what
they <a href=https://www.ietf.org/rfc/rfc4330.txt>document</a> is to find an <a href=https://www.ietf.org/rfc/rfc1769.txt>earlier version</a> to read first.
-(The greybeard community problem where all documentation is written by people
-who don't remember NOT already knowing this stuff.)</p>
+(This is an example of the greybeard community problem, where all current
+documentation was written by people who don't remember NOT already knowing
+this stuff and the resources they originally learned from are long gone.)</p>
<p>That said, RFC documents can be useful (especially for networking protocols)
and the four URL templates the recommended starting files
-for new commands (toys/example/{skeleton,hello}.c) provide point to posix, lsb,
-man, and rfc pages.</p>
+for new commands (hello.c and skeleton.c in the toys/example directory)
+provide point to example posix, lsb, man, and rfc pages online.</p>
<hr />
<a name="dev_env">
@@ -310,18 +320,18 @@ resize2fs tune2fs fsck.ext2 genext2fs mke2fs xzcat
configure, make, and install in each package, and providing basic command line
facilities such as a text editor. (It does not include a compiler toolchain or
C library, those are outside the scope of the toybox project, although mkroot
-has a <a href=https://landley.net/code/qcc>potentialy follow-up project</a>.
+has a <a href=https://landley.net/code/qcc>potential follow-up project</a>.
For now we use distro toolchains,
<a href=https://github.com/richfelker/musl-cross-make>musl-cross-make</a>,
and the Android NDK for build testing.)
-That build system also instaled bash 2.05b as #!/bin/sh and its scripts
+That build system also installed bash 2.05b as #!/bin/sh and its scripts
required bash extensions not present in shells such as busybox ash.
-To replace that toysh needs to supply several bash extensions _and_ work
+To replace that, toysh needs to supply several bash extensions _and_ work
when called under the name "bash".</p>
<p>The above command list was collected using a command line recording wrapper
-(scripts/record-commands and toys/example/logpath.c) which scripts/mkroot.sh
-also uses to populate root/log/*-commands.txt. Try
+(mkroot/record-commands and toys/example/logpath.c) which mkroot/mkroot.sh
+also uses to populate root/build/log/*-commands.txt. Try
<b>awk '{print $1}' root/build/log/*-commands.txt | sort -u | grep -v musl | xargs</b>
after building a mkroot target to see the list of commands called out
of the $PATH during that build.</p>
@@ -351,7 +361,7 @@ project ("mkroot") designed to use an existing cross+native toolchain (such as
or the Android NDK) instead of building its own cross and native compilers
from source. In 2019 the still-incomplete
mkroot was merged into toybox as the "make root" target (which runs
-scripts/mkroot.sh). This is intended
+mkroot/mkroot.sh). This is intended
as a simpler way of providing essentially the same build environment, and doesn't
significantly affect the rest of this analysis (although the "rebuild itself
from source" test should now include building musl-cross-make under either
@@ -453,7 +463,7 @@ replace existing Android versions, so we should take into account Android's use
cases when doing so. This includes:</p>
<blockquote><b>
<span id=toolbox>
-dd getevent gzip modprobe newfs_msdos sh
+getevent gzip modprobe newfs_msdos sh
</span>
</b></blockquote>
@@ -465,7 +475,7 @@ the libmodprobe-based implementation.) These should be a priority for
cleanup:</p>
<blockquote><b>
-bc dd diff expr getfattr lsof more stty tr traceroute
+diff expr getopt tr brctl getfattr lsof modprobe more stty traceroute vi
</b></blockquote>
<p>Android wishlist:</p>
@@ -499,7 +509,7 @@ awk bc bzip2 jar java javap m4 make python python2.7 python3 xz
</b></blockquote>
<p>Subtracting what's already in toybox (including the following toybox toys
-that are still in pending: <code>dd diff expr getopt gzip lsof tr</code>),
+that are still in pending: <code>diff expr gzip lsof tr</code>),
that leaves:</p>
<blockquote><b>
@@ -606,7 +616,7 @@ usleep vi watch wc wget which who whoami xargs xzcat yes zcat
</span>
</b></blockquote>
-
+<p>Nobody seems entirely sure why.</p>
<a name="fhs" />
<hr /><a href=fhs>Filesystem Hierachy Standard</a>
@@ -619,8 +629,8 @@ managed to achieve before they chased away the hobbyists maintaining it.
Only one version (3.0 in 2015) has been released since the Linux Foundation
absorbed the FHS. The previous release, Version 2.3, was released in 2004.
The Linux Foundation did not retain earlier versions. The contents of
-the relevant sections appear identical between the two versions, the
-Linux Foundation just added section numbers.</p>
+the relevant sections appear identical between the two versions, in the
+11 years between releases the Linux Foundation just added section numbers.</p>
<p><a href=https://refspects.linuxfoundation.org/FHS_3.0/fhs-3.0.html>FHS 3.0</a>
section 3.4.2 requires commands to be in the /bin directory, and then 3.4.3
@@ -629,9 +639,9 @@ and then 3.16.2 and 3.16.3 similarly cover /sbin. There are linux
specific sections in 6.1.2 and 6.1.6 but everything in them is obsolete.</p>
<p>The /bin options include csh but not bash, and ed but not vi.
-The /sbin options have update which seems obsolete (filesystem
+The /sbin options have "update" which seems obsolete (filesystem
buffers haven't needed a userspace process to flush them for DECADES),
-fastboot and fasthalt (reboot and halt have -nf), and
+"fastboot" and "fasthalt" (reboot and halt have -nf), and
fsck.* and mkfs.* that don't actually specify any specific filesystems.
Removing that gives us:</p>
@@ -656,15 +666,15 @@ which sed make bash patch gzip bzip2 tar cpio unzip rsync file bc wget
</b></p></blockquote>
<p>(It also lists binutils gcc g++ perl python, and for debian it wants
-build-essential. And it wants file to be in /usr/bin because
+the build-essential meta-package. And it wants file to be in /usr/bin because
<a href=https://git.busybox.net/buildroot/tree/support/dependencies/dependencies.sh?h=2018.02.x#n84>libtool
breaks otherwise</a>.)</p>
<p>Oddly, buildroot can't NOT cross compile. Buildroot does not support a cross toolchain that lives in "/usr/bin"
-with a prefix of "" (if you try, and chop out the test for a blank prefix,
-it dies trying to run "/usr/bin/-gcc"). You can patch your way to
-making it work if you try, but buildroot's developers explicitly do not
-support this.</p>
+with a prefix of "". If you try, and chop out the test for a blank prefix,
+it dies trying to run "/usr/bin/-gcc". In theory you can modify any open source
+project to do anything if you rewrite enough of it, but buildroot's developers
+explicitly do not support this usage model.</p>
<hr /><a name=klibc />
<h2>klibc:</h2>
@@ -702,19 +712,15 @@ which removes mknodes, mksyntax, sha1hash, and fixdep from the list.
"rm -rf -- $@", and minips is more commonly called "ps": I'm not doing aliases
for these oddball names.
The "kinit" command is another gratuitous rename, it's init running as PID 1.
-The halt, poweroff, and reboot commands work with it.</p>
-
-<p>Yet more stale forks of dash and gzip got sucked in here (see "dubious
+The halt, poweroff, and reboot commands work with it.
+Yet more stale forks of dash and gzip got sucked in here (see "dubious
license terms" above).</p>
<p>In theory "blkid" or "file" handle fstype (and df for mounted filesystems),
-but we could do fstype.</p>
-
-<p>We should implement nfsmount, and probably smbmount
-and p9mount even though this hasn't got one. The reason these aren't
-in the base "mount" command is they interactively query login credentials.</p>
-
-<p>The ipconfig command here has a built in dhcp client, so it's ifconfig
+but we could do fstype. We should also implement nfsmount, and probably smbmount
+and p9mount even though this hasn't got one. (The reason these aren't
+in the base "mount" command is they interactively query login credentials.)
+The ipconfig command here has a built in dhcp client, so it's ifconfig
and dhcpcd and maybe some other stuff.</p>
<p>The resume command is... weird. It finds a swap partition and reads data
@@ -769,8 +775,8 @@ non-configurable iconv now that utf8+unicode exist.</li>
unistd.h; it probably belongs in the development toolchain.</li>
<li><b>getent</b> handles retrieving entries from passwd-style databases
(in a rather lame way) and is trivially replacable by grep.</li>
-<li><b>locale</b> was discussed under <a href=#susv4>posix</a>.
-localedef compiles locale definitions, which musl currently does not use.</li>
+<li><b>locale</b> was discussed under <a href=#susv4>posix</a>.</li>
+<li><b>localedef</b> compiles locale definitions, which musl currently does not use.</li>
<li><b>mtrace</b> is a perl script to use the malloc debugging that glibc has built-in;
this is not relevant for musl, and would necessarily vary with libc.</li>
<li><b>nscd</b> is a name service caching daemon, which is not yet relevant for musl.</li>
@@ -794,7 +800,7 @@ outputting a great deal of extra information about each timezone.</li>
<li><b>zic</b> converts a description of a timezone to a file in tz format.</li>
</ul>
-<p>We implemented getconf, and I could see maybe arguing for ncsd.
+<p>We implemented getconf and iconv, and I could see maybe arguing for ncsd.
The rest are not relevant to toybox.</p>
</b></blockquote>
@@ -1394,43 +1400,12 @@ assembler for each architecture.)</p>
<h3>Packages from LFS ch6 toybox does NOT plan to replace:</h3>
-<ul>
-<li><b>linux-api-headers</b></li>
-<li><b>man-pages glibc</b></li>
-<li><b>zlib</b></li>
-<li><b>readline</b></li>
-<li><b>gmp</b></li>
-<li><b>mpfr</b></li>
-<li><b>mpc</b></li>
-<li><b>gcc</b></li>
-<li><b>pkg-config</b></li>
-<li><b>ncurses</b></li>
-<li><b>acl</b></li>
-<li><b>libcap</b></li>
-<li><b>psmisc</b></li>
-<li><b>iana-etc</b></li>
-<li><b>libtool</b></li>
-<li><b>gdbm</b></li>
-<li><b>gperf</b></li>
-<li><b>expat</b></li>
-<li><b>perl</b></li>
-<li><b>XML::Parser</b></li>
-<li><b>intltool</b></li>
-<li><b>autoconf</b></li>
-<li><b>automake</b></li>
-<li><b>gettext</b></li>
-<li><b>libelf</b></li>
-<li><b>libffi</b></li>
-<li><b>openssl</b></li>
-<li><b>python</b></li>
-<li><b>ninja</b></li>
-<li><b>meson</b></li>
-<li><b>check</b></li>
-<li><b>groff</b></li>
-<li><b>grub</b></li>
-<li><b>libpipeline</b></li>
-<li><b>texinfo</b></li>
-</ul>
+<blockquote><p><b>
+linux-api-headers man-pages glibc zlib readline gmp mpfr mpc gcc pkg-config
+ncurses acl libcap psmisc iana-etc libtool gdbm gperf expat perl XML::Parser
+intltool autoconf automake gettext libelf libffi openssl python ninja meson
+check groff grub libpipeline texinfo
+</b></p></blockquote>
<p>That said, we do implement our own zlib and readline replacements, and
presumably _could_ export them as library bindings. Plus we provide
@@ -1447,5 +1422,72 @@ created busybox mdev way back when (which replaces it) and plans to do a
new one for toybox as soon as we work out what subset is still needed now that
devtmpfs is available.</p>
+<hr /><a name=todo /><h2>TODO list</h2>
+
+<ul>
+<li><p>Fill out "development" command list (finish toysh, implement awk, etc.)</p></li>
+
+<p><li>Handle "pending" directory.
+<ul>
+<li>Cleanup and promote the "pending" commands used to run mkroot.</li>
+<ul><li>Enabled by $PENDING in mkroot.sh (sh route)</li></ul>
+
+<li>Cleanup and promote the "pending" commands used to build mkroot.</li>
+<ul><li>In scripts/install.sh the $PENDING list symlinked from the host $PATH
+into "make airlock" directory (expr git tr bash sh gzip awk bison flex make).</li></ul>
+<li>Cleanup and promote all $PENDING commands used by android
+<ul><li><b>grep pending Android.bp</b>
+in <a href=https://android.googlesource.com/platform/external/toybox>their repo</a>
+(diff expr tr brctl getfattr lsof modprobe more stty traceroute vi)</li></ul>
+</li>
+
+<li>Cleanup/promote/delete remaining "pending" commands</li>
+<ul><li>Once empty, remove toys/pending and maybe collape together other
+directories into just toys/*.c (with "default n" meaning examples, and
+a "posix_defconfig" target alongside macos/bsd/android).</li></ul>
+
+</ul></li></p>
+
+<li><p>Replace kconfig/ with a new implementation (menu/def/yes/no/old).</p></li>
+
+<p><li>Automate Linux From Scratch build.
+<ul>
+
+<li>Automate the <a href=https://linuxfromscratch.org/lfs/downloads/stable/LFS-BOOK-12.0-NOCHUNKS.html>existing build</a>
+<ul>
+<li>create chroot directory from host (chapters 4-6)</li>
+<li>setup/launch chroot directory (start of chapter 7)</li>
+<li>build in chroot directory (chapters 7-10)</li>
+</ul>
+</li>
+
+<li>Add record-commands support (both inside and outside chroot)</li>
+<li>Build host-&gt;chroot part with PATH=$PWD/airlock (moving one command over at a time)
+<ul><li>Set up native compiler, enumerate/build/install "temp stuff" toybox
+doesn't provide yet (make, busybox commands, etc).</li></ul>
+</li>
+
+<li>Run host-&gt;chroot build under mkroot, with airlock built+packaged for
+target (toybox, native compiler, temp stuff from busybox or "make")</li>
+<li>Run chroot build to completion in chroot under mkroot (kernel etc smoketest)</li>
+<li>Run chroot build outside chroot (keeping toybox at start of $PATH)
+to prove toybox commands sufficient to build ALL packages</li>
+<li>Package LFS build (mkroot/packages/lfs)
+
+<ul>
+<li>host/chroot/target build scripts</li>
+<li><a href=http://ftp.osuosl.org/pub/lfs/lfs-packages/>download</a> and
+setup packages.</li>
+<li>Note: I already did this <a href=https://github.com/landley/control-images/tree/master/images/lfs-bootstrap/mnt>long ago</a> for LFS 6.7.</li>
+</li>
+</ul>
+
+</ul></p>
+
+<li><p>1.0 release</p></li>
+
+<li><p>Tackle AOSP build.</p></li>
+</ul>
+
<!-- #include "footer.html" -->