Snap for 10453563 from 9323773b0b13f0b51f0874572a4a87ce40855934 to mainline-art-release

Change-Id: I5eadeae56e46eb31f6968fde0980e2be570771f7
diff --git a/.config-device b/.config-device
index 196378e..c90db6d 100644
--- a/.config-device
+++ b/.config-device
@@ -7,34 +7,22 @@
 #
 
 CONFIG_TOYBOX=y
-CONFIG_TOYBOX_CONTAINER=y
-# CONFIG_TOYBOX_COPYFILERANGE is not set
 # CONFIG_TOYBOX_DEBUG is not set
-CONFIG_TOYBOX_FALLOCATE=y
-CONFIG_TOYBOX_FIFREEZE=y
 CONFIG_TOYBOX_FLOAT=y
 CONFIG_TOYBOX_FORK=y
 # CONFIG_TOYBOX_FREE is not set
-# CONFIG_TOYBOX_GETRANDOM is not set
 CONFIG_TOYBOX_HELP_DASHDASH=y
 CONFIG_TOYBOX_HELP=y
-CONFIG_TOYBOX_I18N=y
-CONFIG_TOYBOX_ICONV=y
 CONFIG_TOYBOX_LIBCRYPTO=y
 CONFIG_TOYBOX_LIBZ=y
 # CONFIG_TOYBOX_LSM_NONE is not set
-# CONFIG_TOYBOX_MUSL_NOMMU_IS_BROKEN is not set
 CONFIG_TOYBOX_NORECURSE=y
 CONFIG_TOYBOX_ON_ANDROID=y
-CONFIG_TOYBOX_ANDROID_SCHEDPOLICY=y
-# CONFIG_TOYBOX_PEDANTIC_ARGS is not set
 CONFIG_TOYBOX_SELINUX=y
-# CONFIG_TOYBOX_SHADOW is not set
 # CONFIG_TOYBOX_SMACK is not set
 # CONFIG_TOYBOX_SUID is not set
 CONFIG_TOYBOX_UID_SYS=100
 CONFIG_TOYBOX_UID_USR=500
-# CONFIG_TOYBOX_UTMPX is not set
 
 #
 # Selected toys.
@@ -53,12 +41,10 @@
 CONFIG_BLKID=y
 CONFIG_BLOCKDEV=y
 # CONFIG_BOOTCHARTD is not set
-# CONFIG_BRCTL is not set
+CONFIG_BRCTL=y
 # CONFIG_BUNZIP2 is not set
 # CONFIG_BZCAT is not set
 CONFIG_CAL=y
-# CONFIG_CATV is not set
-CONFIG_CAT_V=y
 CONFIG_CAT=y
 # CONFIG_CD is not set
 CONFIG_CHATTR=y
@@ -74,11 +60,8 @@
 CONFIG_CLEAR=y
 CONFIG_CMP=y
 CONFIG_COMM=y
-# CONFIG_COMPRESS is not set
 # CONFIG_COUNT is not set
 CONFIG_CPIO=y
-CONFIG_CP_MORE=y
-CONFIG_CP_PRESERVE=y
 CONFIG_CP=y
 # CONFIG_CRC32 is not set
 # CONFIG_CROND is not set
@@ -88,7 +71,6 @@
 CONFIG_DD=y
 # CONFIG_DEALLOCVT is not set
 # CONFIG_DEBUG_DHCP is not set
-# CONFIG_DECOMPRESS is not set
 # CONFIG_DEMO_MANY_OPTIONS is not set
 # CONFIG_DEMO_NUMBER is not set
 # CONFIG_DEMO_SCANKEY is not set
@@ -135,6 +117,12 @@
 CONFIG_GETFATTR=y
 CONFIG_GETOPT=y
 # CONFIG_GETTY is not set
+# CONFIG_GITCHECKOUT is not set
+# CONFIG_GITCLONE is not set
+# CONFIG_GITCOMPAT is not set
+# CONFIG_GITFETCH is not set
+# CONFIG_GITINIT is not set
+# CONFIG_GITREMOTE is not set
 # CONFIG_GPIODETECT is not set
 # CONFIG_GPIOFIND is not set
 # CONFIG_GPIOGET is not set
@@ -148,7 +136,6 @@
 CONFIG_GZIP=y
 CONFIG_HEAD=y
 # CONFIG_HELLO is not set
-CONFIG_HELP_EXTRAS=y
 CONFIG_HELP=y
 # CONFIG_HEXDUMP is not set
 # CONFIG_HEXEDIT is not set
@@ -156,6 +143,7 @@
 # CONFIG_HOSTID is not set
 # CONFIG_HOST is not set
 CONFIG_HOSTNAME=y
+# CONFIG_HTTPD is not set
 CONFIG_HWCLOCK=y
 CONFIG_I2CDETECT=y
 CONFIG_I2CDUMP=y
@@ -185,22 +173,18 @@
 # CONFIG_LINUX32 is not set
 CONFIG_LN=y
 CONFIG_LOAD_POLICY=y
-# CONFIG_LOGGER is not set
+CONFIG_LOGGER=y
 # CONFIG_LOGIN is not set
 CONFIG_LOGNAME=y
 # CONFIG_LOGPATH is not set
 CONFIG_LOG=y
-# CONFIG_LOGWRAPPER is not set
 CONFIG_LOSETUP=y
 CONFIG_LSATTR=y
-CONFIG_LS_COLOR=y
 CONFIG_LSMOD=y
 CONFIG_LSOF=y
 CONFIG_LSPCI=y
-CONFIG_LSPCI_TEXT=y
 CONFIG_LSUSB=y
 CONFIG_LS=y
-CONFIG_LS_Z=y
 CONFIG_MAKEDEVS=y
 # CONFIG_MAN is not set
 # CONFIG_MCOOKIE is not set
@@ -219,7 +203,6 @@
 CONFIG_MKFIFO=y
 CONFIG_MKFIFO_Z=y
 CONFIG_MKNOD=y
-CONFIG_MKNOD=y
 CONFIG_MKNOD_Z=y
 # CONFIG_MKPASSWD is not set
 CONFIG_MKSWAP=y
@@ -229,10 +212,9 @@
 CONFIG_MORE=y
 CONFIG_MOUNTPOINT=y
 CONFIG_MOUNT=y
-CONFIG_MV_MORE=y
 CONFIG_MV=y
 CONFIG_NBD_CLIENT=y
-CONFIG_NETCAT_LISTEN=y
+# CONFIG_NBD_SERVER is not set
 CONFIG_NETCAT=y
 CONFIG_NETSTAT=y
 CONFIG_NICE=y
@@ -250,7 +232,6 @@
 CONFIG_PGREP=y
 CONFIG_PIDOF=y
 CONFIG_PING=y
-CONFIG_PING6=y
 CONFIG_PIVOT_ROOT=y
 CONFIG_PKILL=y
 CONFIG_PMAP=y
@@ -290,12 +271,11 @@
 CONFIG_SHA512SUM=y
 # CONFIG_SH is not set
 # CONFIG_SHRED is not set
+# CONFIG_SHUF is not set
 # CONFIG_SKELETON_ALIAS is not set
 # CONFIG_SKELETON is not set
-CONFIG_SLEEP_FLOAT=y
 CONFIG_SLEEP=y
 # CONFIG_SNTP is not set
-CONFIG_SORT_BIG=y
 CONFIG_SORT_FLOAT=y
 CONFIG_SORT=y
 CONFIG_SPLIT=y
@@ -312,11 +292,9 @@
 CONFIG_SYSCTL=y
 # CONFIG_SYSLOGD is not set
 CONFIG_TAC=y
-CONFIG_TAIL_SEEK=y
 CONFIG_TAIL=y
 CONFIG_TAR=y
 CONFIG_TASKSET=y
-CONFIG_TASKSET=y
 # CONFIG_TCPSVD is not set
 CONFIG_TEE=y
 # CONFIG_TELNETD is not set
@@ -333,7 +311,6 @@
 CONFIG_TRUE=y
 CONFIG_TRUNCATE=y
 CONFIG_TR=y
-# CONFIG_TTOP is not set
 CONFIG_TTY=y
 CONFIG_TUNCTL=y
 CONFIG_UCLAMPSET=y
@@ -363,7 +340,6 @@
 CONFIG_WHOAMI=y
 # CONFIG_WHO is not set
 # CONFIG_W is not set
-# CONFIG_XARGS_PEDANTIC is not set
 CONFIG_XARGS=y
 CONFIG_XXD=y
 # CONFIG_XZCAT is not set
diff --git a/.config-linux b/.config-linux
index 0a54259..73e55ac 100644
--- a/.config-linux
+++ b/.config-linux
@@ -6,36 +6,23 @@
 # General settings.
 #
 
-# CONFIG_TOYBOX_ANDROID_SCHEDPOLICY is not set
-# CONFIG_TOYBOX_CONTAINER is not set
-# CONFIG_TOYBOX_COPYFILERANGE is not set
+CONFIG_TOYBOX=y
 # CONFIG_TOYBOX_DEBUG is not set
-# CONFIG_TOYBOX_FALLOCATE is not set
-# CONFIG_TOYBOX_FIFREEZE is not set
 CONFIG_TOYBOX_FLOAT=y
 CONFIG_TOYBOX_FORK=y
 # CONFIG_TOYBOX_FREE is not set
-# CONFIG_TOYBOX_GETRANDOM is not set
 CONFIG_TOYBOX_HELP_DASHDASH=y
 CONFIG_TOYBOX_HELP=y
-CONFIG_TOYBOX_I18N=y
-CONFIG_TOYBOX_ICONV=y
 CONFIG_TOYBOX_LIBCRYPTO=y
 CONFIG_TOYBOX_LIBZ=y
 CONFIG_TOYBOX_LSM_NONE=y
-# CONFIG_TOYBOX_MUSL_NOMMU_IS_BROKEN is not set
-# CONFIG_TOYBOX_NORECURSE is not set
+CONFIG_TOYBOX_NORECURSE=y
 # CONFIG_TOYBOX_ON_ANDROID is not set
-# CONFIG_TOYBOX_PEDANTIC_ARGS is not set
-# CONFIG_TOYBOX_PRLIMIT is not set
 # CONFIG_TOYBOX_SELINUX is not set
-# CONFIG_TOYBOX_SHADOW is not set
 # CONFIG_TOYBOX_SMACK is not set
-CONFIG_TOYBOX_SUID=y
+# CONFIG_TOYBOX_SUID is not set
 CONFIG_TOYBOX_UID_SYS=100
 CONFIG_TOYBOX_UID_USR=500
-# CONFIG_TOYBOX_UTMPX is not set
-CONFIG_TOYBOX=y
 
 #
 # Selected toys.
@@ -58,8 +45,6 @@
 # CONFIG_BUNZIP2 is not set
 # CONFIG_BZCAT is not set
 # CONFIG_CAL is not set
-# CONFIG_CATV is not set
-CONFIG_CAT_V=y
 CONFIG_CAT=y
 # CONFIG_CD is not set
 # CONFIG_CHATTR is not set
@@ -77,7 +62,6 @@
 CONFIG_COMM=y
 # CONFIG_COUNT is not set
 CONFIG_CPIO=y
-CONFIG_CP_PRESERVE=y
 CONFIG_CP=y
 # CONFIG_CRC32 is not set
 # CONFIG_CROND is not set
@@ -115,7 +99,7 @@
 # CONFIG_FALSE is not set
 # CONFIG_FDISK is not set
 CONFIG_FGREP=y
-# CONFIG_FILE is not set
+CONFIG_FILE=y
 CONFIG_FIND=y
 # CONFIG_FLOCK is not set
 # CONFIG_FMT is not set
@@ -133,6 +117,12 @@
 # CONFIG_GETFATTR is not set
 CONFIG_GETOPT=y
 # CONFIG_GETTY is not set
+# CONFIG_GITCHECKOUT is not set
+# CONFIG_GITCLONE is not set
+# CONFIG_GITCOMPAT is not set
+# CONFIG_GITFETCH is not set
+# CONFIG_GITINIT is not set
+# CONFIG_GITREMOTE is not set
 # CONFIG_GPIODETECT is not set
 # CONFIG_GPIOFIND is not set
 # CONFIG_GPIOGET is not set
@@ -146,7 +136,6 @@
 CONFIG_GZIP=y
 CONFIG_HEAD=y
 # CONFIG_HELLO is not set
-# CONFIG_HELP_EXTRAS is not set
 # CONFIG_HELP is not set
 # CONFIG_HEXDUMP is not set
 # CONFIG_HEXEDIT is not set
@@ -154,6 +143,7 @@
 # CONFIG_HOSTID is not set
 # CONFIG_HOST is not set
 CONFIG_HOSTNAME=y
+# CONFIG_HTTPD is not set
 # CONFIG_HWCLOCK is not set
 # CONFIG_I2CDETECT is not set
 # CONFIG_I2CDUMP is not set
@@ -188,13 +178,11 @@
 # CONFIG_LOG is not set
 # CONFIG_LOGNAME is not set
 # CONFIG_LOGPATH is not set
-# CONFIG_LOGWRAPPER is not set
 # CONFIG_LOSETUP is not set
 # CONFIG_LSATTR is not set
 # CONFIG_LSMOD is not set
 # CONFIG_LSOF is not set
 # CONFIG_LSPCI is not set
-# CONFIG_LSPCI_TEXT is not set
 # CONFIG_LSUSB is not set
 CONFIG_LS=y
 # CONFIG_MAKEDEVS is not set
@@ -226,8 +214,8 @@
 # CONFIG_MOUNTPOINT is not set
 CONFIG_MV=y
 # CONFIG_NBD_CLIENT is not set
+# CONFIG_NBD_SERVER is not set
 # CONFIG_NETCAT is not set
-# CONFIG_NETCAT_LISTEN is not set
 # CONFIG_NETSTAT is not set
 # CONFIG_NICE is not set
 CONFIG_NL=y
@@ -284,6 +272,7 @@
 CONFIG_SHA512SUM=y
 # CONFIG_SH is not set
 # CONFIG_SHRED is not set
+# CONFIG_SHUF is not set
 # CONFIG_SKELETON_ALIAS is not set
 # CONFIG_SKELETON is not set
 CONFIG_SLEEP=y
@@ -352,7 +341,6 @@
 CONFIG_WHOAMI=y
 # CONFIG_WHO is not set
 # CONFIG_W is not set
-# CONFIG_XARGS_PEDANTIC is not set
 CONFIG_XARGS=y
 CONFIG_XXD=y
 # CONFIG_XZCAT is not set
diff --git a/.config-mac b/.config-mac
index 3770579..6ff9493 100644
--- a/.config-mac
+++ b/.config-mac
@@ -6,36 +6,23 @@
 # General settings.
 #
 
-# CONFIG_TOYBOX_ANDROID_SCHEDPOLICY is not set
-# CONFIG_TOYBOX_CONTAINER is not set
-# CONFIG_TOYBOX_COPYFILERANGE is not set
+CONFIG_TOYBOX=y
 # CONFIG_TOYBOX_DEBUG is not set
-# CONFIG_TOYBOX_FALLOCATE is not set
-# CONFIG_TOYBOX_FIFREEZE is not set
 CONFIG_TOYBOX_FLOAT=y
 CONFIG_TOYBOX_FORK=y
 # CONFIG_TOYBOX_FREE is not set
-# CONFIG_TOYBOX_GETRANDOM is not set
 CONFIG_TOYBOX_HELP_DASHDASH=y
 CONFIG_TOYBOX_HELP=y
-CONFIG_TOYBOX_I18N=y
-CONFIG_TOYBOX_ICONV=y
 CONFIG_TOYBOX_LIBCRYPTO=y
 CONFIG_TOYBOX_LIBZ=y
 CONFIG_TOYBOX_LSM_NONE=y
-# CONFIG_TOYBOX_MUSL_NOMMU_IS_BROKEN is not set
-# CONFIG_TOYBOX_NORECURSE is not set
+CONFIG_TOYBOX_NORECURSE=y
 # CONFIG_TOYBOX_ON_ANDROID is not set
-# CONFIG_TOYBOX_PEDANTIC_ARGS is not set
-# CONFIG_TOYBOX_PRLIMIT is not set
 # CONFIG_TOYBOX_SELINUX is not set
-# CONFIG_TOYBOX_SHADOW is not set
 # CONFIG_TOYBOX_SMACK is not set
-CONFIG_TOYBOX_SUID=y
+# CONFIG_TOYBOX_SUID is not set
 CONFIG_TOYBOX_UID_SYS=100
 CONFIG_TOYBOX_UID_USR=500
-# CONFIG_TOYBOX_UTMPX is not set
-CONFIG_TOYBOX=y
 
 #
 # Selected toys.
@@ -58,8 +45,6 @@
 # CONFIG_BUNZIP2 is not set
 # CONFIG_BZCAT is not set
 # CONFIG_CAL is not set
-# CONFIG_CATV is not set
-CONFIG_CAT_V=y
 CONFIG_CAT=y
 # CONFIG_CD is not set
 # CONFIG_CHATTR is not set
@@ -77,7 +62,6 @@
 CONFIG_COMM=y
 # CONFIG_COUNT is not set
 CONFIG_CPIO=y
-CONFIG_CP_PRESERVE=y
 CONFIG_CP=y
 # CONFIG_CRC32 is not set
 # CONFIG_CROND is not set
@@ -115,7 +99,7 @@
 # CONFIG_FALSE is not set
 # CONFIG_FDISK is not set
 CONFIG_FGREP=y
-# CONFIG_FILE is not set
+CONFIG_FILE=y
 CONFIG_FIND=y
 # CONFIG_FLOCK is not set
 # CONFIG_FMT is not set
@@ -133,6 +117,12 @@
 # CONFIG_GETFATTR is not set
 CONFIG_GETOPT=y
 # CONFIG_GETTY is not set
+# CONFIG_GITCHECKOUT is not set
+# CONFIG_GITCLONE is not set
+# CONFIG_GITCOMPAT is not set
+# CONFIG_GITFETCH is not set
+# CONFIG_GITINIT is not set
+# CONFIG_GITREMOTE is not set
 # CONFIG_GPIODETECT is not set
 # CONFIG_GPIOFIND is not set
 # CONFIG_GPIOGET is not set
@@ -146,7 +136,6 @@
 CONFIG_GZIP=y
 CONFIG_HEAD=y
 # CONFIG_HELLO is not set
-# CONFIG_HELP_EXTRAS is not set
 # CONFIG_HELP is not set
 # CONFIG_HEXDUMP is not set
 # CONFIG_HEXEDIT is not set
@@ -154,6 +143,7 @@
 # CONFIG_HOSTID is not set
 # CONFIG_HOST is not set
 CONFIG_HOSTNAME=y
+# CONFIG_HTTPD is not set
 # CONFIG_HWCLOCK is not set
 # CONFIG_I2CDETECT is not set
 # CONFIG_I2CDUMP is not set
@@ -188,13 +178,11 @@
 # CONFIG_LOG is not set
 # CONFIG_LOGNAME is not set
 # CONFIG_LOGPATH is not set
-# CONFIG_LOGWRAPPER is not set
 # CONFIG_LOSETUP is not set
 # CONFIG_LSATTR is not set
 # CONFIG_LSMOD is not set
 # CONFIG_LSOF is not set
 # CONFIG_LSPCI is not set
-# CONFIG_LSPCI_TEXT is not set
 # CONFIG_LSUSB is not set
 CONFIG_LS=y
 # CONFIG_MAKEDEVS is not set
@@ -226,8 +214,8 @@
 # CONFIG_MOUNTPOINT is not set
 CONFIG_MV=y
 # CONFIG_NBD_CLIENT is not set
+# CONFIG_NBD_SERVER is not set
 # CONFIG_NETCAT is not set
-# CONFIG_NETCAT_LISTEN is not set
 # CONFIG_NETSTAT is not set
 # CONFIG_NICE is not set
 CONFIG_NL=y
@@ -284,6 +272,7 @@
 CONFIG_SHA512SUM=y
 # CONFIG_SH is not set
 # CONFIG_SHRED is not set
+# CONFIG_SHUF is not set
 # CONFIG_SKELETON_ALIAS is not set
 # CONFIG_SKELETON is not set
 CONFIG_SLEEP=y
@@ -352,7 +341,6 @@
 CONFIG_WHOAMI=y
 # CONFIG_WHO is not set
 # CONFIG_W is not set
-# CONFIG_XARGS_PEDANTIC is not set
 CONFIG_XARGS=y
 CONFIG_XXD=y
 # CONFIG_XZCAT is not set
diff --git a/.github/workflows/toybox.yml b/.github/workflows/toybox.yml
index 7940321..a2f0621 100644
--- a/.github/workflows/toybox.yml
+++ b/.github/workflows/toybox.yml
@@ -7,22 +7,8 @@
     branches: [ master ]
 
 jobs:
-  MacOS-11_0:
-    runs-on: macos-11.0
-
-    steps:
-    - uses: actions/checkout@v2
-    - name: Setup
-      run: brew install gnu-sed
-    - name: Configure
-      run: make macos_defconfig
-    - name: Build
-      run: make
-    - name: Test
-      run: VERBOSE=all make tests
-
-  MacOS-10_15:
-    runs-on: macos-10.15
+  MacOS-12:
+    runs-on: macos-12
 
     steps:
     - uses: actions/checkout@v2
diff --git a/Android.bp b/Android.bp
index a8e7491..f6a0610 100644
--- a/Android.bp
+++ b/Android.bp
@@ -98,6 +98,7 @@
     "toys/posix/du.c",
     "toys/posix/echo.c",
     "toys/posix/env.c",
+    "toys/posix/file.c",
     "toys/posix/find.c",
     "toys/posix/getconf.c",
     "toys/posix/grep.c",
@@ -209,6 +210,7 @@
     "toys/other/vconfig.c",
     "toys/other/vmstat.c",
     "toys/other/watch.c",
+    "toys/pending/brctl.c",
     "toys/pending/getfattr.c",
     "toys/pending/lsof.c",
     "toys/pending/modprobe.c",
@@ -222,9 +224,9 @@
     "toys/posix/df.c",
     "toys/posix/expand.c",
     "toys/posix/false.c",
-    "toys/posix/file.c",
     "toys/posix/iconv.c",
     "toys/posix/kill.c",
+    "toys/posix/logger.c",
     "toys/posix/mkfifo.c",
     "toys/posix/nice.c",
     "toys/posix/nohup.c",
@@ -245,6 +247,7 @@
     "base64",
     "basename",
     "blockdev",
+    "brctl",
     "cal",
     "cat",
     "chattr",
@@ -310,6 +313,7 @@
     "load_policy",
     "ln",
     "log",
+    "logger",
     "logname",
     "losetup",
     "ls",
@@ -406,6 +410,7 @@
     "uudecode",
     "uuencode",
     "uuidgen",
+    "vi",
     "vmstat",
     "watch",
     "wc",
@@ -427,6 +432,7 @@
         "-Werror",
         "-Wno-char-subscripts",
         "-Wno-deprecated-declarations",
+        "-Wno-invalid-source-encoding",
         "-Wno-missing-field-initializers",
         "-Wno-pointer-arith",
         "-Wno-sign-compare",
diff --git a/METADATA b/METADATA
index 191882c..0f8e19e 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,7 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update toybox
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+
 name: "toybox"
 description: "Toybox: all-in-one Linux command line."
 third_party {
@@ -9,11 +13,11 @@
     type: GIT
     value: "https://github.com/landley/toybox"
   }
-  version: "8b97a1fb86b06e329c77c64cdbef29d7738f5840"
+  version: "d45ee3a2bc6271110312f01be867a9b6b91dd07f"
   license_type: UNENCUMBERED
   last_upgrade_date {
-    year: 2022
+    year: 2023
     month: 4
-    day: 18
+    day: 19
   }
 }
diff --git a/Makefile b/Makefile
index 4098702..52f0851 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,7 @@
 
 .PHONY: clean distclean baseline bloatcheck install install_flat \
 	uninstall uninstall_flat tests help change \
-	list list_working list_pending root run_root
+	list list_example list_pending root run_root
 .SUFFIXES: # Disable legacy behavior
 
 include kconfig/Makefile
@@ -73,14 +73,14 @@
 	@rm -f toybox* .config* .singlemake
 	@echo removed .config
 
-tests:
+tests: toybox
 	scripts/test.sh
 
 root:
-	scripts/mkroot.sh $(MAKEFLAGS)
+	mkroot/mkroot.sh $(MAKEFLAGS)
 
 run_root:
-	cd root/"$${CROSS:-host}" && ./qemu-*.sh
+	cd root/"$${CROSS:-host}" && ./run-qemu.sh
 
 help::
 	@cat scripts/help.txt
diff --git a/README b/README
index f39c921..580459b 100644
--- a/README
+++ b/README
@@ -39,12 +39,12 @@
 prefixed cross compiler toolchain, several example toolchains (built using
 the file "scripts/mcm-buildall.sh" in the toybox source) are available at:
 
-  https://mkroot.musl.cc/latest/
+  https://landley.net/toybox/downloads/binaries/toolchains/latest
 
 For the "CROSS_COMPILE=armv5l-" example above, download
-cross-compiler-armv5l.tar.bz2, extract it, and add its "bin" subdirectory to
-your $PATH. (And yes, the trailing - is significant, because the prefix
-includes a dash.)
+armv5l-linux-musleabihf-cross.tar.xz, extract it, and add its "bin"
+subdirectory to your $PATH. (And yes, the trailing - is significant,
+because the prefix includes a dash.)
 
 For more about cross compiling, see:
 
diff --git a/TEST_MAPPING b/TEST_MAPPING
index cdb4934..6e9020a 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -2,11 +2,19 @@
   "presubmit": [
     {
       "name": "toybox-tests"
+    },
+    {
+      "name": "aidl_integration_test"
     }
   ],
   "hwasan-postsubmit": [
     {
       "name": "toybox-tests"
     }
+  ],
+  "kernel-presubmit": [
+    {
+      "name": "toybox-tests"
+    }
   ]
 }
diff --git a/android/device/generated/config.h b/android/device/generated/config.h
index 415d99e..f260bf1 100644
--- a/android/device/generated/config.h
+++ b/android/device/generated/config.h
@@ -1,59 +1,35 @@
 #define CFG_TOYBOX 1
 #define USE_TOYBOX(...) __VA_ARGS__
-#define CFG_TOYBOX_CONTAINER 1
-#define USE_TOYBOX_CONTAINER(...) __VA_ARGS__
-#define CFG_TOYBOX_COPYFILERANGE 0
-#define USE_TOYBOX_COPYFILERANGE(...)
 #define CFG_TOYBOX_DEBUG 0
 #define USE_TOYBOX_DEBUG(...)
-#define CFG_TOYBOX_FALLOCATE 1
-#define USE_TOYBOX_FALLOCATE(...) __VA_ARGS__
-#define CFG_TOYBOX_FIFREEZE 1
-#define USE_TOYBOX_FIFREEZE(...) __VA_ARGS__
 #define CFG_TOYBOX_FLOAT 1
 #define USE_TOYBOX_FLOAT(...) __VA_ARGS__
 #define CFG_TOYBOX_FORK 1
 #define USE_TOYBOX_FORK(...) __VA_ARGS__
 #define CFG_TOYBOX_FREE 0
 #define USE_TOYBOX_FREE(...)
-#define CFG_TOYBOX_GETRANDOM 0
-#define USE_TOYBOX_GETRANDOM(...)
 #define CFG_TOYBOX_HELP_DASHDASH 1
 #define USE_TOYBOX_HELP_DASHDASH(...) __VA_ARGS__
 #define CFG_TOYBOX_HELP 1
 #define USE_TOYBOX_HELP(...) __VA_ARGS__
-#define CFG_TOYBOX_I18N 1
-#define USE_TOYBOX_I18N(...) __VA_ARGS__
-#define CFG_TOYBOX_ICONV 1
-#define USE_TOYBOX_ICONV(...) __VA_ARGS__
 #define CFG_TOYBOX_LIBCRYPTO 1
 #define USE_TOYBOX_LIBCRYPTO(...) __VA_ARGS__
 #define CFG_TOYBOX_LIBZ 1
 #define USE_TOYBOX_LIBZ(...) __VA_ARGS__
 #define CFG_TOYBOX_LSM_NONE 0
 #define USE_TOYBOX_LSM_NONE(...)
-#define CFG_TOYBOX_MUSL_NOMMU_IS_BROKEN 0
-#define USE_TOYBOX_MUSL_NOMMU_IS_BROKEN(...)
 #define CFG_TOYBOX_NORECURSE 1
 #define USE_TOYBOX_NORECURSE(...) __VA_ARGS__
 #define CFG_TOYBOX_ON_ANDROID 1
 #define USE_TOYBOX_ON_ANDROID(...) __VA_ARGS__
-#define CFG_TOYBOX_ANDROID_SCHEDPOLICY 1
-#define USE_TOYBOX_ANDROID_SCHEDPOLICY(...) __VA_ARGS__
-#define CFG_TOYBOX_PEDANTIC_ARGS 0
-#define USE_TOYBOX_PEDANTIC_ARGS(...)
 #define CFG_TOYBOX_SELINUX 1
 #define USE_TOYBOX_SELINUX(...) __VA_ARGS__
-#define CFG_TOYBOX_SHADOW 0
-#define USE_TOYBOX_SHADOW(...)
 #define CFG_TOYBOX_SMACK 0
 #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_UTMPX 0
-#define USE_TOYBOX_UTMPX(...)
 #define CFG_ACPI 1
 #define USE_ACPI(...) __VA_ARGS__
 #define CFG_ARCH 0
@@ -80,18 +56,14 @@
 #define USE_BLOCKDEV(...) __VA_ARGS__
 #define CFG_BOOTCHARTD 0
 #define USE_BOOTCHARTD(...)
-#define CFG_BRCTL 0
-#define USE_BRCTL(...)
+#define CFG_BRCTL 1
+#define USE_BRCTL(...) __VA_ARGS__
 #define CFG_BUNZIP2 0
 #define USE_BUNZIP2(...)
 #define CFG_BZCAT 0
 #define USE_BZCAT(...)
 #define CFG_CAL 1
 #define USE_CAL(...) __VA_ARGS__
-#define CFG_CATV 0
-#define USE_CATV(...)
-#define CFG_CAT_V 1
-#define USE_CAT_V(...) __VA_ARGS__
 #define CFG_CAT 1
 #define USE_CAT(...) __VA_ARGS__
 #define CFG_CD 0
@@ -122,16 +94,10 @@
 #define USE_CMP(...) __VA_ARGS__
 #define CFG_COMM 1
 #define USE_COMM(...) __VA_ARGS__
-#define CFG_COMPRESS 0
-#define USE_COMPRESS(...)
 #define CFG_COUNT 0
 #define USE_COUNT(...)
 #define CFG_CPIO 1
 #define USE_CPIO(...) __VA_ARGS__
-#define CFG_CP_MORE 1
-#define USE_CP_MORE(...) __VA_ARGS__
-#define CFG_CP_PRESERVE 1
-#define USE_CP_PRESERVE(...) __VA_ARGS__
 #define CFG_CP 1
 #define USE_CP(...) __VA_ARGS__
 #define CFG_CRC32 0
@@ -150,8 +116,6 @@
 #define USE_DEALLOCVT(...)
 #define CFG_DEBUG_DHCP 0
 #define USE_DEBUG_DHCP(...)
-#define CFG_DECOMPRESS 0
-#define USE_DECOMPRESS(...)
 #define CFG_DEMO_MANY_OPTIONS 0
 #define USE_DEMO_MANY_OPTIONS(...)
 #define CFG_DEMO_NUMBER 0
@@ -244,6 +208,18 @@
 #define USE_GETOPT(...) __VA_ARGS__
 #define CFG_GETTY 0
 #define USE_GETTY(...)
+#define CFG_GITCHECKOUT 0
+#define USE_GITCHECKOUT(...)
+#define CFG_GITCLONE 0
+#define USE_GITCLONE(...)
+#define CFG_GITCOMPAT 0
+#define USE_GITCOMPAT(...)
+#define CFG_GITFETCH 0
+#define USE_GITFETCH(...)
+#define CFG_GITINIT 0
+#define USE_GITINIT(...)
+#define CFG_GITREMOTE 0
+#define USE_GITREMOTE(...)
 #define CFG_GPIODETECT 0
 #define USE_GPIODETECT(...)
 #define CFG_GPIOFIND 0
@@ -270,8 +246,6 @@
 #define USE_HEAD(...) __VA_ARGS__
 #define CFG_HELLO 0
 #define USE_HELLO(...)
-#define CFG_HELP_EXTRAS 1
-#define USE_HELP_EXTRAS(...) __VA_ARGS__
 #define CFG_HELP 1
 #define USE_HELP(...) __VA_ARGS__
 #define CFG_HEXDUMP 0
@@ -286,6 +260,8 @@
 #define USE_HOST(...)
 #define CFG_HOSTNAME 1
 #define USE_HOSTNAME(...) __VA_ARGS__
+#define CFG_HTTPD 0
+#define USE_HTTPD(...)
 #define CFG_HWCLOCK 1
 #define USE_HWCLOCK(...) __VA_ARGS__
 #define CFG_I2CDETECT 1
@@ -344,8 +320,8 @@
 #define USE_LN(...) __VA_ARGS__
 #define CFG_LOAD_POLICY 1
 #define USE_LOAD_POLICY(...) __VA_ARGS__
-#define CFG_LOGGER 0
-#define USE_LOGGER(...)
+#define CFG_LOGGER 1
+#define USE_LOGGER(...) __VA_ARGS__
 #define CFG_LOGIN 0
 #define USE_LOGIN(...)
 #define CFG_LOGNAME 1
@@ -354,28 +330,20 @@
 #define USE_LOGPATH(...)
 #define CFG_LOG 1
 #define USE_LOG(...) __VA_ARGS__
-#define CFG_LOGWRAPPER 0
-#define USE_LOGWRAPPER(...)
 #define CFG_LOSETUP 1
 #define USE_LOSETUP(...) __VA_ARGS__
 #define CFG_LSATTR 1
 #define USE_LSATTR(...) __VA_ARGS__
-#define CFG_LS_COLOR 1
-#define USE_LS_COLOR(...) __VA_ARGS__
 #define CFG_LSMOD 1
 #define USE_LSMOD(...) __VA_ARGS__
 #define CFG_LSOF 1
 #define USE_LSOF(...) __VA_ARGS__
 #define CFG_LSPCI 1
 #define USE_LSPCI(...) __VA_ARGS__
-#define CFG_LSPCI_TEXT 1
-#define USE_LSPCI_TEXT(...) __VA_ARGS__
 #define CFG_LSUSB 1
 #define USE_LSUSB(...) __VA_ARGS__
 #define CFG_LS 1
 #define USE_LS(...) __VA_ARGS__
-#define CFG_LS_Z 1
-#define USE_LS_Z(...) __VA_ARGS__
 #define CFG_MAKEDEVS 1
 #define USE_MAKEDEVS(...) __VA_ARGS__
 #define CFG_MAN 0
@@ -412,8 +380,6 @@
 #define USE_MKFIFO_Z(...) __VA_ARGS__
 #define CFG_MKNOD 1
 #define USE_MKNOD(...) __VA_ARGS__
-#define CFG_MKNOD 1
-#define USE_MKNOD(...) __VA_ARGS__
 #define CFG_MKNOD_Z 1
 #define USE_MKNOD_Z(...) __VA_ARGS__
 #define CFG_MKPASSWD 0
@@ -432,14 +398,12 @@
 #define USE_MOUNTPOINT(...) __VA_ARGS__
 #define CFG_MOUNT 1
 #define USE_MOUNT(...) __VA_ARGS__
-#define CFG_MV_MORE 1
-#define USE_MV_MORE(...) __VA_ARGS__
 #define CFG_MV 1
 #define USE_MV(...) __VA_ARGS__
 #define CFG_NBD_CLIENT 1
 #define USE_NBD_CLIENT(...) __VA_ARGS__
-#define CFG_NETCAT_LISTEN 1
-#define USE_NETCAT_LISTEN(...) __VA_ARGS__
+#define CFG_NBD_SERVER 0
+#define USE_NBD_SERVER(...)
 #define CFG_NETCAT 1
 #define USE_NETCAT(...) __VA_ARGS__
 #define CFG_NETSTAT 1
@@ -474,8 +438,6 @@
 #define USE_PIDOF(...) __VA_ARGS__
 #define CFG_PING 1
 #define USE_PING(...) __VA_ARGS__
-#define CFG_PING6 1
-#define USE_PING6(...) __VA_ARGS__
 #define CFG_PIVOT_ROOT 1
 #define USE_PIVOT_ROOT(...) __VA_ARGS__
 #define CFG_PKILL 1
@@ -554,18 +516,16 @@
 #define USE_SH(...)
 #define CFG_SHRED 0
 #define USE_SHRED(...)
+#define CFG_SHUF 0
+#define USE_SHUF(...)
 #define CFG_SKELETON_ALIAS 0
 #define USE_SKELETON_ALIAS(...)
 #define CFG_SKELETON 0
 #define USE_SKELETON(...)
-#define CFG_SLEEP_FLOAT 1
-#define USE_SLEEP_FLOAT(...) __VA_ARGS__
 #define CFG_SLEEP 1
 #define USE_SLEEP(...) __VA_ARGS__
 #define CFG_SNTP 0
 #define USE_SNTP(...)
-#define CFG_SORT_BIG 1
-#define USE_SORT_BIG(...) __VA_ARGS__
 #define CFG_SORT_FLOAT 1
 #define USE_SORT_FLOAT(...) __VA_ARGS__
 #define CFG_SORT 1
@@ -598,16 +558,12 @@
 #define USE_SYSLOGD(...)
 #define CFG_TAC 1
 #define USE_TAC(...) __VA_ARGS__
-#define CFG_TAIL_SEEK 1
-#define USE_TAIL_SEEK(...) __VA_ARGS__
 #define CFG_TAIL 1
 #define USE_TAIL(...) __VA_ARGS__
 #define CFG_TAR 1
 #define USE_TAR(...) __VA_ARGS__
 #define CFG_TASKSET 1
 #define USE_TASKSET(...) __VA_ARGS__
-#define CFG_TASKSET 1
-#define USE_TASKSET(...) __VA_ARGS__
 #define CFG_TCPSVD 0
 #define USE_TCPSVD(...)
 #define CFG_TEE 1
@@ -640,8 +596,6 @@
 #define USE_TRUNCATE(...) __VA_ARGS__
 #define CFG_TR 1
 #define USE_TR(...) __VA_ARGS__
-#define CFG_TTOP 0
-#define USE_TTOP(...)
 #define CFG_TTY 1
 #define USE_TTY(...) __VA_ARGS__
 #define CFG_TUNCTL 1
@@ -700,8 +654,6 @@
 #define USE_WHO(...)
 #define CFG_W 0
 #define USE_W(...)
-#define CFG_XARGS_PEDANTIC 0
-#define USE_XARGS_PEDANTIC(...)
 #define CFG_XARGS 1
 #define USE_XARGS(...) __VA_ARGS__
 #define CFG_XXD 1
diff --git a/android/device/generated/flags.h b/android/device/generated/flags.h
index ced393d..ef9fc67 100644
--- a/android/device/generated/flags.h
+++ b/android/device/generated/flags.h
@@ -1,11 +1,8 @@
 #undef FORCED_FLAG
-#undef FORCED_FLAGLL
 #ifdef FORCE_FLAGS
-#define FORCED_FLAG 1
-#define FORCED_FLAGLL 1ULL
+#define FORCED_FLAG 1LL
 #else
-#define FORCED_FLAG 0
-#define FORCED_FLAGLL 0LL
+#define FORCED_FLAG 0LL
 #endif
 
 // acpi abctV abctV
@@ -131,13 +128,14 @@
 #undef FLAG_f
 #endif
 
-// blkid ULs*[!LU] ULs*[!LU]
+// blkid ULo:s*[!LU] ULo:s*[!LU]
 #undef OPTSTR_blkid
-#define OPTSTR_blkid "ULs*[!LU]"
+#define OPTSTR_blkid "ULo:s*[!LU]"
 #ifdef CLEANUP_blkid
 #undef CLEANUP_blkid
 #undef FOR_blkid
 #undef FLAG_s
+#undef FLAG_o
 #undef FLAG_L
 #undef FLAG_U
 #endif
@@ -171,7 +169,7 @@
 #undef FOR_bootchartd
 #endif
 
-// brctl   <1
+// brctl <1 <1
 #undef OPTSTR_brctl
 #define OPTSTR_brctl "<1"
 #ifdef CLEANUP_brctl
@@ -221,17 +219,6 @@
 #undef FLAG_u
 #endif
 
-// catv   vte
-#undef OPTSTR_catv
-#define OPTSTR_catv "vte"
-#ifdef CLEANUP_catv
-#undef CLEANUP_catv
-#undef FOR_catv
-#undef FLAG_e
-#undef FLAG_t
-#undef FLAG_v
-#endif
-
 // cd   >1LP[-LP]
 #undef OPTSTR_cd
 #define OPTSTR_cd ">1LP[-LP]"
@@ -323,9 +310,9 @@
 #undef FLAG_s
 #endif
 
-// chvt   <1
+// chvt   <1>1
 #undef OPTSTR_chvt
-#define OPTSTR_chvt "<1"
+#define OPTSTR_chvt "<1>1"
 #ifdef CLEANUP_chvt
 #undef CLEANUP_chvt
 #undef FOR_chvt
@@ -410,9 +397,9 @@
 #undef FLAG_preserve
 #endif
 
-// cpio (ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF] (ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]
+// cpio (ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)R(owner):md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF] (ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)R(owner):md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]
 #undef OPTSTR_cpio
-#define OPTSTR_cpio "(ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]"
+#define OPTSTR_cpio "(ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)R(owner):md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]"
 #ifdef CLEANUP_cpio
 #undef CLEANUP_cpio
 #undef FOR_cpio
@@ -426,6 +413,7 @@
 #undef FLAG_u
 #undef FLAG_d
 #undef FLAG_m
+#undef FLAG_R
 #undef FLAG_no_preserve_owner
 #undef FLAG_quiet
 #undef FLAG_renumber_inodes
@@ -468,9 +456,9 @@
 #undef FLAG_c
 #endif
 
-// cut b*|c*|f*|F*|C*|O(output-delimiter):d:sDn[!cbfF] b*|c*|f*|F*|C*|O(output-delimiter):d:sDn[!cbfF]
+// cut b*|c*|f*|F(regex-fields)*|C*|O(output-delimiter):d:sD(allow-duplicates)n[!cbfF] b*|c*|f*|F(regex-fields)*|C*|O(output-delimiter):d:sD(allow-duplicates)n[!cbfF]
 #undef OPTSTR_cut
-#define OPTSTR_cut "b*|c*|f*|F*|C*|O(output-delimiter):d:sDn[!cbfF]"
+#define OPTSTR_cut "b*|c*|f*|F(regex-fields)*|C*|O(output-delimiter):d:sD(allow-duplicates)n[!cbfF]"
 #ifdef CLEANUP_cut
 #undef CLEANUP_cut
 #undef FOR_cut
@@ -486,9 +474,9 @@
 #undef FLAG_b
 #endif
 
-// date d:D:I(iso)(iso-8601):;r:s:u(utc)[!dr] d:D:I(iso)(iso-8601):;r:s:u(utc)[!dr]
+// date d:D:I(iso-8601):;r:s:u(utc)[!dr] d:D:I(iso-8601):;r:s:u(utc)[!dr]
 #undef OPTSTR_date
-#define OPTSTR_date "d:D:I(iso)(iso-8601):;r:s:u(utc)[!dr]"
+#define OPTSTR_date "d:D:I(iso-8601):;r:s:u(utc)[!dr]"
 #ifdef CLEANUP_date
 #undef CLEANUP_date
 #undef FOR_date
@@ -714,17 +702,18 @@
 #undef FLAG_P
 #endif
 
-// diff <2>2(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)L(label)*S(starting-file):N(new-file)r(recursive)U(unified)#<0=3 <2>2(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)L(label)*S(starting-file):N(new-file)r(recursive)U(unified)#<0=3
+// diff <2>2(unchanged-line-format):;(old-line-format):;(new-line-format):;(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)S(starting-file):F(show-function-line):;L(label)*N(new-file)r(recursive)U(unified)#<0=3 <2>2(unchanged-line-format):;(old-line-format):;(new-line-format):;(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)S(starting-file):F(show-function-line):;L(label)*N(new-file)r(recursive)U(unified)#<0=3
 #undef OPTSTR_diff
-#define OPTSTR_diff "<2>2(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)L(label)*S(starting-file):N(new-file)r(recursive)U(unified)#<0=3"
+#define OPTSTR_diff "<2>2(unchanged-line-format):;(old-line-format):;(new-line-format):;(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)S(starting-file):F(show-function-line):;L(label)*N(new-file)r(recursive)U(unified)#<0=3"
 #ifdef CLEANUP_diff
 #undef CLEANUP_diff
 #undef FOR_diff
 #undef FLAG_U
 #undef FLAG_r
 #undef FLAG_N
-#undef FLAG_S
 #undef FLAG_L
+#undef FLAG_F
+#undef FLAG_S
 #undef FLAG_a
 #undef FLAG_q
 #undef FLAG_s
@@ -738,6 +727,9 @@
 #undef FLAG_B
 #undef FLAG_strip_trailing_cr
 #undef FLAG_color
+#undef FLAG_new_line_format
+#undef FLAG_old_line_format
+#undef FLAG_unchanged_line_format
 #endif
 
 // dirname <1 <1
@@ -900,12 +892,14 @@
 #undef FOR_expr
 #endif
 
-// factor    
+// factor   ?hx
 #undef OPTSTR_factor
-#define OPTSTR_factor 0
+#define OPTSTR_factor "?hx"
 #ifdef CLEANUP_factor
 #undef CLEANUP_factor
 #undef FOR_factor
+#undef FLAG_x
+#undef FLAG_h
 #endif
 
 // fallocate >1l#|o# >1l#|o#
@@ -940,9 +934,9 @@
 #undef FLAG_C
 #endif
 
-// file <1bhLs[!hL] <1bhLs[!hL]
+// file <1b(brief)hLs[!hL] <1b(brief)hLs[!hL]
 #undef OPTSTR_file
-#define OPTSTR_file "<1bhLs[!hL]"
+#define OPTSTR_file "<1b(brief)hLs[!hL]"
 #ifdef CLEANUP_file
 #undef CLEANUP_file
 #undef FOR_file
@@ -1144,6 +1138,46 @@
 #undef FLAG_t
 #endif
 
+// gitcheckout   <1
+#undef OPTSTR_gitcheckout
+#define OPTSTR_gitcheckout "<1"
+#ifdef CLEANUP_gitcheckout
+#undef CLEANUP_gitcheckout
+#undef FOR_gitcheckout
+#endif
+
+// gitclone   <1
+#undef OPTSTR_gitclone
+#define OPTSTR_gitclone "<1"
+#ifdef CLEANUP_gitclone
+#undef CLEANUP_gitclone
+#undef FOR_gitclone
+#endif
+
+// gitfetch    
+#undef OPTSTR_gitfetch
+#define OPTSTR_gitfetch 0
+#ifdef CLEANUP_gitfetch
+#undef CLEANUP_gitfetch
+#undef FOR_gitfetch
+#endif
+
+// gitinit   <1
+#undef OPTSTR_gitinit
+#define OPTSTR_gitinit "<1"
+#ifdef CLEANUP_gitinit
+#undef CLEANUP_gitinit
+#undef FOR_gitinit
+#endif
+
+// gitremote   <1
+#undef OPTSTR_gitremote
+#define OPTSTR_gitremote "<1"
+#ifdef CLEANUP_gitremote
+#undef CLEANUP_gitremote
+#undef FOR_gitremote
+#endif
+
 // gpiodetect   >0
 #undef OPTSTR_gpiodetect
 #define OPTSTR_gpiodetect ">0"
@@ -1186,9 +1220,9 @@
 #undef FLAG_l
 #endif
 
-// grep (line-buffered)(color):;(exclude-dir)*S(exclude)*M(include)*ZzEFHIab(byte-offset)h(no-filename)ino(only-matching)rRsvwcL(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)rRsvwcL(files-without-match)l(files-with-matches)q(quiet)(silent)e*f*C#B#A#m#x[!wx][!EF]
+// 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)rRsvwcL(files-without-match)l(files-with-matches)q(quiet)(silent)e*f*C#B#A#m#x[!wx][!EF]"
+#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
@@ -1253,9 +1287,9 @@
 #undef FOR_groups
 #endif
 
-// gunzip cdfk123456789[-123456789] cdfk123456789[-123456789]
+// gunzip cdfkt123456789[-123456789] cdfkt123456789[-123456789]
 #undef OPTSTR_gunzip
-#define OPTSTR_gunzip "cdfk123456789[-123456789]"
+#define OPTSTR_gunzip "cdfkt123456789[-123456789]"
 #ifdef CLEANUP_gunzip
 #undef CLEANUP_gunzip
 #undef FOR_gunzip
@@ -1268,15 +1302,16 @@
 #undef FLAG_3
 #undef FLAG_2
 #undef FLAG_1
+#undef FLAG_t
 #undef FLAG_k
 #undef FLAG_f
 #undef FLAG_d
 #undef FLAG_c
 #endif
 
-// gzip ncdfk123456789[-123456789] ncdfk123456789[-123456789]
+// gzip n(no-name)cdfkt123456789[-123456789] n(no-name)cdfkt123456789[-123456789]
 #undef OPTSTR_gzip
-#define OPTSTR_gzip "ncdfk123456789[-123456789]"
+#define OPTSTR_gzip "n(no-name)cdfkt123456789[-123456789]"
 #ifdef CLEANUP_gzip
 #undef CLEANUP_gzip
 #undef FOR_gzip
@@ -1289,6 +1324,7 @@
 #undef FLAG_3
 #undef FLAG_2
 #undef FLAG_1
+#undef FLAG_t
 #undef FLAG_k
 #undef FLAG_f
 #undef FLAG_d
@@ -1385,6 +1421,15 @@
 #undef FLAG_b
 #endif
 
+// httpd   >1v
+#undef OPTSTR_httpd
+#define OPTSTR_httpd ">1v"
+#ifdef CLEANUP_httpd
+#undef CLEANUP_httpd
+#undef FOR_httpd
+#undef FLAG_v
+#endif
+
 // hwclock >0(fast)f(rtc):u(utc)l(localtime)t(systz)s(hctosys)r(show)w(systohc)[-ul][!rtsw] >0(fast)f(rtc):u(utc)l(localtime)t(systz)s(hctosys)r(show)w(systohc)[-ul][!rtsw]
 #undef OPTSTR_hwclock
 #define OPTSTR_hwclock ">0(fast)f(rtc):u(utc)l(localtime)t(systz)s(hctosys)r(show)w(systohc)[-ul][!rtsw]"
@@ -1425,9 +1470,9 @@
 #undef FLAG_f
 #endif
 
-// i2cget <3>3fy <3>3fy
+// i2cget <2>3fy <2>3fy
 #undef OPTSTR_i2cget
-#define OPTSTR_i2cget "<3>3fy"
+#define OPTSTR_i2cget "<2>3fy"
 #ifdef CLEANUP_i2cget
 #undef CLEANUP_i2cget
 #undef FOR_i2cget
@@ -1505,9 +1550,9 @@
 #undef FOR_insmod
 #endif
 
-// install <1cdDpsvt:m:o:g: <1cdDpsvt:m:o:g:
+// install <1cdDp(preserve-timestamps)svt:m:o:g: <1cdDp(preserve-timestamps)svt:m:o:g:
 #undef OPTSTR_install
-#define OPTSTR_install "<1cdDpsvt:m:o:g:"
+#define OPTSTR_install "<1cdDp(preserve-timestamps)svt:m:o:g:"
 #ifdef CLEANUP_install
 #undef CLEANUP_install
 #undef FOR_install
@@ -1723,7 +1768,7 @@
 #undef FLAG_p
 #endif
 
-// logger   t:p:s
+// logger t:p:s t:p:s
 #undef OPTSTR_logger
 #define OPTSTR_logger "t:p:s"
 #ifdef CLEANUP_logger
@@ -1779,9 +1824,9 @@
 #undef FLAG_S
 #endif
 
-// ls (color):;(full-time)(show-control-chars)ZgoACFHLRSabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][!qb] (color):;(full-time)(show-control-chars)ZgoACFHLRSabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][!qb]
+// ls (sort):(color):;(full-time)(show-control-chars)¡(group-directories-first)þZgoACFHLNRSUXabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][-Nqb] (sort):(color):;(full-time)(show-control-chars)¡(group-directories-first)þZgoACFHLNRSUXabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][-Nqb]
 #undef OPTSTR_ls
-#define OPTSTR_ls "(color):;(full-time)(show-control-chars)ZgoACFHLRSabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][!qb]"
+#define OPTSTR_ls "(sort):(color):;(full-time)(show-control-chars)¡(group-directories-first)þZgoACFHLNRSUXabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][-Nqb]"
 #ifdef CLEANUP_ls
 #undef CLEANUP_ls
 #undef FOR_ls
@@ -1805,8 +1850,11 @@
 #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
@@ -1815,9 +1863,12 @@
 #undef FLAG_o
 #undef FLAG_g
 #undef FLAG_Z
+#undef FLAG_X7E
+#undef FLAG_X21
 #undef FLAG_show_control_chars
 #undef FLAG_full_time
 #undef FLAG_color
+#undef FLAG_sort
 #endif
 
 // lsattr ldapvR ldapvR
@@ -1853,13 +1904,14 @@
 #undef FLAG_l
 #endif
 
-// lspci emkn@i: emkn@i:
+// lspci emkn@x@i: emkn@x@i:
 #undef OPTSTR_lspci
-#define OPTSTR_lspci "emkn@i:"
+#define OPTSTR_lspci "emkn@x@i:"
 #ifdef CLEANUP_lspci
 #undef CLEANUP_lspci
 #undef FOR_lspci
 #undef FLAG_i
+#undef FLAG_x
 #undef FLAG_n
 #undef FLAG_k
 #undef FLAG_m
@@ -2065,9 +2117,9 @@
 #undef FOR_more
 #endif
 
-// mount ?O:afnrvwt:o*[-rw] ?O:afnrvwt:o*[-rw]
+// mount ?RO:afnrvwt:o*[-rw] ?RO:afnrvwt:o*[-rw]
 #undef OPTSTR_mount
-#define OPTSTR_mount "?O:afnrvwt:o*[-rw]"
+#define OPTSTR_mount "?RO:afnrvwt:o*[-rw]"
 #ifdef CLEANUP_mount
 #undef CLEANUP_mount
 #undef FOR_mount
@@ -2080,6 +2132,7 @@
 #undef FLAG_f
 #undef FLAG_a
 #undef FLAG_O
+#undef FLAG_R
 #endif
 
 // mountpoint <1qdx[-dx] <1qdx[-dx]
@@ -2093,9 +2146,9 @@
 #undef FLAG_q
 #endif
 
-// mv <1vnF(remove-destination)fit:T[-ni] <1vnF(remove-destination)fit:T[-ni]
+// mv <1v(verbose)nF(remove-destination)fit:T[-ni] <1v(verbose)nF(remove-destination)fit:T[-ni]
 #undef OPTSTR_mv
-#define OPTSTR_mv "<1vnF(remove-destination)fit:T[-ni]"
+#define OPTSTR_mv "<1v(verbose)nF(remove-destination)fit:T[-ni]"
 #ifdef CLEANUP_mv
 #undef CLEANUP_mv
 #undef FOR_mv
@@ -2108,22 +2161,33 @@
 #undef FLAG_v
 #endif
 
-// nbd_client <3>3ns <3>3ns
+// nbd_client <3>3b#<1>4294967295=4096ns <3>3b#<1>4294967295=4096ns
 #undef OPTSTR_nbd_client
-#define OPTSTR_nbd_client "<3>3ns"
+#define OPTSTR_nbd_client "<3>3b#<1>4294967295=4096ns"
 #ifdef CLEANUP_nbd_client
 #undef CLEANUP_nbd_client
 #undef FOR_nbd_client
 #undef FLAG_s
 #undef FLAG_n
+#undef FLAG_b
 #endif
 
-// netcat ^tElLw#<1W#<1p#<1>65535q#<1s:f:46uU[!tlL][!Lw][!46U] ^tElLw#<1W#<1p#<1>65535q#<1s:f:46uU[!tlL][!Lw][!46U]
+// nbd_server   <1>1r
+#undef OPTSTR_nbd_server
+#define OPTSTR_nbd_server "<1>1r"
+#ifdef CLEANUP_nbd_server
+#undef CLEANUP_nbd_server
+#undef FOR_nbd_server
+#undef FLAG_r
+#endif
+
+// netcat ^tElLw#<1W#<1p#<1>65535q#<1s:f:46uUn[!tlL][!Lw][!Lu][!46U] ^tElLw#<1W#<1p#<1>65535q#<1s:f:46uUn[!tlL][!Lw][!Lu][!46U]
 #undef OPTSTR_netcat
-#define OPTSTR_netcat "^tElLw#<1W#<1p#<1>65535q#<1s:f:46uU[!tlL][!Lw][!46U]"
+#define OPTSTR_netcat "^tElLw#<1W#<1p#<1>65535q#<1s:f:46uUn[!tlL][!Lw][!Lu][!46U]"
 #ifdef CLEANUP_netcat
 #undef CLEANUP_netcat
 #undef FOR_netcat
+#undef FLAG_n
 #undef FLAG_U
 #undef FLAG_u
 #undef FLAG_6
@@ -2200,9 +2264,9 @@
 #undef FLAG_all
 #endif
 
-// nsenter <1F(no-fork)t#<1(target)i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user); <1F(no-fork)t#<1(target)i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user);
+// nsenter <1a(all)F(no-fork)t#<1(target)C(cgroup):; i(ipc):; m(mount):; n(net):; p(pid):; u(uts):; U(user):;  <1a(all)F(no-fork)t#<1(target)C(cgroup):; i(ipc):; m(mount):; n(net):; p(pid):; u(uts):; U(user):; 
 #undef OPTSTR_nsenter
-#define OPTSTR_nsenter "<1F(no-fork)t#<1(target)i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user);"
+#define OPTSTR_nsenter "<1a(all)F(no-fork)t#<1(target)C(cgroup):; i(ipc):; m(mount):; n(net):; p(pid):; u(uts):; U(user):; "
 #ifdef CLEANUP_nsenter
 #undef CLEANUP_nsenter
 #undef FOR_nsenter
@@ -2212,8 +2276,10 @@
 #undef FLAG_n
 #undef FLAG_m
 #undef FLAG_i
+#undef FLAG_C
 #undef FLAG_t
 #undef FLAG_F
+#undef FLAG_a
 #endif
 
 // od j#vw#<1=16N#xsodcbA:t* j#vw#<1=16N#xsodcbA:t*
@@ -2521,17 +2587,36 @@
 #undef FLAG_dyn_syms
 #endif
 
-// readlink <1nqmef(canonicalize)[-mef] <1nqmef(canonicalize)[-mef]
+// readlink <1vnf(canonicalize)emqz[-mef][-qv] <1vnf(canonicalize)emqz[-mef][-qv]
 #undef OPTSTR_readlink
-#define OPTSTR_readlink "<1nqmef(canonicalize)[-mef]"
+#define OPTSTR_readlink "<1vnf(canonicalize)emqz[-mef][-qv]"
 #ifdef CLEANUP_readlink
 #undef CLEANUP_readlink
 #undef FOR_readlink
-#undef FLAG_f
-#undef FLAG_e
-#undef FLAG_m
+#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] <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
 
 // reboot   d:fn
@@ -2595,9 +2680,9 @@
 #undef FOR_rfkill
 #endif
 
-// rm fiRrv[-fi] fiRrv[-fi]
+// rm f(force)iRrv[-fi] f(force)iRrv[-fi]
 #undef OPTSTR_rm
-#define OPTSTR_rm "fiRrv[-fi]"
+#define OPTSTR_rm "f(force)iRrv[-fi]"
 #ifdef CLEANUP_rm
 #undef CLEANUP_rm
 #undef FOR_rm
@@ -2657,17 +2742,17 @@
 #undef FLAG_list_modes
 #endif
 
-// runcon <2 <2
+// runcon ^<2 ^<2
 #undef OPTSTR_runcon
-#define OPTSTR_runcon "<2"
+#define OPTSTR_runcon "^<2"
 #ifdef CLEANUP_runcon
 #undef CLEANUP_runcon
 #undef FOR_runcon
 #endif
 
-// sed (help)(version)e*f*i:;nErz(null-data)s[+Er] (help)(version)e*f*i:;nErz(null-data)s[+Er]
+// 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)e*f*i:;nErz(null-data)s[+Er]"
+#define OPTSTR_sed "(help)(version)(tarxform)e*f*i:;nErz(null-data)s[+Er]"
 #ifdef CLEANUP_sed
 #undef CLEANUP_sed
 #undef FOR_sed
@@ -2679,6 +2764,7 @@
 #undef FLAG_i
 #undef FLAG_f
 #undef FLAG_e
+#undef FLAG_tarxform
 #undef FLAG_version
 #undef FLAG_help
 #endif
@@ -2789,9 +2875,20 @@
 #undef FLAG_z
 #endif
 
-// skeleton   (walrus)(blubber):;(also):e@d*c#b:a
+// shuf   zen#<0
+#undef OPTSTR_shuf
+#define OPTSTR_shuf "zen#<0"
+#ifdef CLEANUP_shuf
+#undef CLEANUP_shuf
+#undef FOR_shuf
+#undef FLAG_n
+#undef FLAG_e
+#undef FLAG_z
+#endif
+
+// skeleton   (walrus)(blubber):;(also):h(hlong):; g(glong): f(longf):;e@d*c#b:a
 #undef OPTSTR_skeleton
-#define OPTSTR_skeleton "(walrus)(blubber):;(also):e@d*c#b:a"
+#define OPTSTR_skeleton "(walrus)(blubber):;(also):h(hlong):; g(glong): f(longf):;e@d*c#b:a"
 #ifdef CLEANUP_skeleton
 #undef CLEANUP_skeleton
 #undef FOR_skeleton
@@ -2800,6 +2897,9 @@
 #undef FLAG_c
 #undef FLAG_d
 #undef FLAG_e
+#undef FLAG_f
+#undef FLAG_g
+#undef FLAG_h
 #undef FLAG_also
 #undef FLAG_blubber
 #undef FLAG_walrus
@@ -2843,9 +2943,9 @@
 #undef FLAG_M
 #endif
 
-// sort gS:T:mo:k*t:xVbMcszdfirun gS:T:mo:k*t:xVbMcszdfirun
+// sort gS:T:mo:k*t:xVbMCcszdfirun gS:T:mo:k*t:xVbMCcszdfirun
 #undef OPTSTR_sort
-#define OPTSTR_sort "gS:T:mo:k*t:xVbMcszdfirun"
+#define OPTSTR_sort "gS:T:mo:k*t:xVbMCcszdfirun"
 #ifdef CLEANUP_sort
 #undef CLEANUP_sort
 #undef FOR_sort
@@ -2858,6 +2958,7 @@
 #undef FLAG_z
 #undef FLAG_s
 #undef FLAG_c
+#undef FLAG_C
 #undef FLAG_M
 #undef FLAG_b
 #undef FLAG_V
@@ -2962,12 +3063,14 @@
 #undef FLAG_t
 #endif
 
-// swapoff <1>1 <1>1
+// swapoff <1>1av <1>1av
 #undef OPTSTR_swapoff
-#define OPTSTR_swapoff "<1>1"
+#define OPTSTR_swapoff "<1>1av"
 #ifdef CLEANUP_swapoff
 #undef CLEANUP_swapoff
 #undef FOR_swapoff
+#undef FLAG_v
+#undef FLAG_a
 #endif
 
 // swapon <1>1p#<0>32767d <1>1p#<0>32767d
@@ -3057,15 +3160,17 @@
 #undef FLAG_f
 #endif
 
-// tar &(strip-components)#(selinux)(restrict)(full-time)(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mode):(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)I(use-compress-program):J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):a[!txc][!jzJa] &(strip-components)#(selinux)(restrict)(full-time)(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mode):(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)I(use-compress-program):J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):a[!txc][!jzJa]
+// tar &(no-ignore-case)(ignore-case)(no-anchored)(anchored)(no-wildcards)(wildcards)(no-wildcards-match-slash)(wildcards-match-slash)(show-transformed-names)(selinux)(restrict)(full-time)(no-recursion)(null)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(sort);:(mode):(mtime):(group):(owner):(to-command):~(strip-components)(strip)#~(transform)(xform)*o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*I(use-compress-program):C(directory):f(file):as[!txc][!jzJa] &(no-ignore-case)(ignore-case)(no-anchored)(anchored)(no-wildcards)(wildcards)(no-wildcards-match-slash)(wildcards-match-slash)(show-transformed-names)(selinux)(restrict)(full-time)(no-recursion)(null)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(sort);:(mode):(mtime):(group):(owner):(to-command):~(strip-components)(strip)#~(transform)(xform)*o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*I(use-compress-program):C(directory):f(file):as[!txc][!jzJa]
 #undef OPTSTR_tar
-#define OPTSTR_tar "&(strip-components)#(selinux)(restrict)(full-time)(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mode):(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)I(use-compress-program):J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):a[!txc][!jzJa]"
+#define OPTSTR_tar "&(no-ignore-case)(ignore-case)(no-anchored)(anchored)(no-wildcards)(wildcards)(no-wildcards-match-slash)(wildcards-match-slash)(show-transformed-names)(selinux)(restrict)(full-time)(no-recursion)(null)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(sort);:(mode):(mtime):(group):(owner):(to-command):~(strip-components)(strip)#~(transform)(xform)*o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*I(use-compress-program):C(directory):f(file):as[!txc][!jzJa]"
 #ifdef CLEANUP_tar
 #undef CLEANUP_tar
 #undef FOR_tar
+#undef FLAG_s
 #undef FLAG_a
 #undef FLAG_f
 #undef FLAG_C
+#undef FLAG_I
 #undef FLAG_T
 #undef FLAG_X
 #undef FLAG_m
@@ -3075,7 +3180,6 @@
 #undef FLAG_z
 #undef FLAG_j
 #undef FLAG_J
-#undef FLAG_I
 #undef FLAG_v
 #undef FLAG_t
 #undef FLAG_x
@@ -3084,20 +3188,32 @@
 #undef FLAG_k
 #undef FLAG_p
 #undef FLAG_o
+#undef FLAG_xform
+#undef FLAG_strip
 #undef FLAG_to_command
 #undef FLAG_owner
 #undef FLAG_group
 #undef FLAG_mtime
 #undef FLAG_mode
+#undef FLAG_sort
 #undef FLAG_exclude
 #undef FLAG_overwrite
 #undef FLAG_no_same_permissions
 #undef FLAG_numeric_owner
+#undef FLAG_null
 #undef FLAG_no_recursion
 #undef FLAG_full_time
 #undef FLAG_restrict
 #undef FLAG_selinux
-#undef FLAG_strip_components
+#undef FLAG_show_transformed_names
+#undef FLAG_wildcards_match_slash
+#undef FLAG_no_wildcards_match_slash
+#undef FLAG_wildcards
+#undef FLAG_no_wildcards
+#undef FLAG_anchored
+#undef FLAG_no_anchored
+#undef FLAG_ignore_case
+#undef FLAG_no_ignore_case
 #endif
 
 // taskset <1^pa <1^pa
@@ -3110,9 +3226,9 @@
 #undef FLAG_p
 #endif
 
-// tcpsvd   ^<3c#=30<1C:b#=20<0u:l:hEv
+// tcpsvd   ^<3c#=30<1b#=20<0C:u:l:hEv
 #undef OPTSTR_tcpsvd
-#define OPTSTR_tcpsvd "^<3c#=30<1C:b#=20<0u:l:hEv"
+#define OPTSTR_tcpsvd "^<3c#=30<1b#=20<0C:u:l:hEv"
 #ifdef CLEANUP_tcpsvd
 #undef CLEANUP_tcpsvd
 #undef FOR_tcpsvd
@@ -3121,8 +3237,8 @@
 #undef FLAG_h
 #undef FLAG_l
 #undef FLAG_u
-#undef FLAG_b
 #undef FLAG_C
+#undef FLAG_b
 #undef FLAG_c
 #endif
 
@@ -3204,12 +3320,13 @@
 #undef FLAG_p
 #endif
 
-// timeout <2^(foreground)(preserve-status)vk:s(signal): <2^(foreground)(preserve-status)vk:s(signal):
+// timeout <2^(foreground)(preserve-status)vk:s(signal):i <2^(foreground)(preserve-status)vk:s(signal):i
 #undef OPTSTR_timeout
-#define OPTSTR_timeout "<2^(foreground)(preserve-status)vk:s(signal):"
+#define OPTSTR_timeout "<2^(foreground)(preserve-status)vk:s(signal):i"
 #ifdef CLEANUP_timeout
 #undef CLEANUP_timeout
 #undef FOR_timeout
+#undef FLAG_i
 #undef FLAG_s
 #undef FLAG_k
 #undef FLAG_v
@@ -3400,9 +3517,9 @@
 #undef FLAG_c
 #endif
 
-// uname aomvrns aomvrns
+// uname paomvrns paomvrns
 #undef OPTSTR_uname
-#define OPTSTR_uname "aomvrns"
+#define OPTSTR_uname "paomvrns"
 #ifdef CLEANUP_uname
 #undef CLEANUP_uname
 #undef FOR_uname
@@ -3413,6 +3530,7 @@
 #undef FLAG_m
 #undef FLAG_o
 #undef FLAG_a
+#undef FLAG_p
 #endif
 
 // unicode   <1
@@ -3466,9 +3584,9 @@
 #undef FLAG_f
 #endif
 
-// unshare <1^f(fork);r(map-root-user);i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user); <1^f(fork);r(map-root-user);i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user);
+// unshare <1^a(all)f(fork)r(map-root-user)C(cgroup):; i(ipc):; m(mount):; n(net):; p(pid):; u(uts):; U(user):;  <1^a(all)f(fork)r(map-root-user)C(cgroup):; i(ipc):; m(mount):; n(net):; p(pid):; u(uts):; U(user):; 
 #undef OPTSTR_unshare
-#define OPTSTR_unshare "<1^f(fork);r(map-root-user);i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user);"
+#define OPTSTR_unshare "<1^a(all)f(fork)r(map-root-user)C(cgroup):; i(ipc):; m(mount):; n(net):; p(pid):; u(uts):; U(user):; "
 #ifdef CLEANUP_unshare
 #undef CLEANUP_unshare
 #undef FOR_unshare
@@ -3478,8 +3596,10 @@
 #undef FLAG_n
 #undef FLAG_m
 #undef FLAG_i
+#undef FLAG_C
 #undef FLAG_r
 #undef FLAG_f
+#undef FLAG_a
 #endif
 
 // uptime >0ps >0ps
@@ -3517,9 +3637,9 @@
 #undef FLAG_r
 #endif
 
-// usleep <1 <1
+// usleep <1>1 <1>1
 #undef OPTSTR_usleep
-#define OPTSTR_usleep "<1"
+#define OPTSTR_usleep "<1>1"
 #ifdef CLEANUP_usleep
 #undef CLEANUP_usleep
 #undef FOR_usleep
@@ -3661,9 +3781,9 @@
 #undef FLAG_a
 #endif
 
-// xargs ^E:P#<0=1optrn#<1(max-args)s#0[!0E] ^E:P#<0=1optrn#<1(max-args)s#0[!0E]
+// 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=1optrn#<1(max-args)s#0[!0E]"
+#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
@@ -3678,9 +3798,9 @@
 #undef FLAG_E
 #endif
 
-// xxd >1c#<0>256l#o#g#<1=2iprs#[!rs] >1c#<0>256l#o#g#<1=2iprs#[!rs]
+// xxd >1c#<0>256l#o#g#<0=2eiprs#[!rs][!re] >1c#<0>256l#o#g#<0=2eiprs#[!rs][!re]
 #undef OPTSTR_xxd
-#define OPTSTR_xxd ">1c#<0>256l#o#g#<1=2iprs#[!rs]"
+#define OPTSTR_xxd ">1c#<0>256l#o#g#<0=2eiprs#[!rs][!re]"
 #ifdef CLEANUP_xxd
 #undef CLEANUP_xxd
 #undef FOR_xxd
@@ -3688,6 +3808,7 @@
 #undef FLAG_r
 #undef FLAG_p
 #undef FLAG_i
+#undef FLAG_e
 #undef FLAG_g
 #undef FLAG_o
 #undef FLAG_l
@@ -3710,9 +3831,9 @@
 #undef FOR_yes
 #endif
 
-// zcat cdfk123456789[-123456789] cdfk123456789[-123456789]
+// zcat cdfkt123456789[-123456789] cdfkt123456789[-123456789]
 #undef OPTSTR_zcat
-#define OPTSTR_zcat "cdfk123456789[-123456789]"
+#define OPTSTR_zcat "cdfkt123456789[-123456789]"
 #ifdef CLEANUP_zcat
 #undef CLEANUP_zcat
 #undef FOR_zcat
@@ -3725,6 +3846,7 @@
 #undef FLAG_3
 #undef FLAG_2
 #undef FLAG_1
+#undef FLAG_t
 #undef FLAG_k
 #undef FLAG_f
 #undef FLAG_d
@@ -3736,11 +3858,11 @@
 #ifndef TT
 #define TT this.acpi
 #endif
-#define FLAG_V (1<<0)
-#define FLAG_t (1<<1)
-#define FLAG_c (1<<2)
-#define FLAG_b (1<<3)
-#define FLAG_a (1<<4)
+#define FLAG_V (1LL<<0)
+#define FLAG_t (1LL<<1)
+#define FLAG_c (1LL<<2)
+#define FLAG_b (1LL<<3)
+#define FLAG_a (1LL<<4)
 #endif
 
 #ifdef FOR_arch
@@ -3806,9 +3928,9 @@
 #ifndef TT
 #define TT this.base64
 #endif
-#define FLAG_w (1<<0)
-#define FLAG_i (1<<1)
-#define FLAG_d (1<<2)
+#define FLAG_w (1LL<<0)
+#define FLAG_i (1LL<<1)
+#define FLAG_d (1LL<<2)
 #endif
 
 #ifdef FOR_basename
@@ -3816,8 +3938,8 @@
 #ifndef TT
 #define TT this.basename
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_a (1<<1)
+#define FLAG_s (1LL<<0)
+#define FLAG_a (1LL<<1)
 #endif
 
 #ifdef FOR_bc
@@ -3837,11 +3959,11 @@
 #ifndef TT
 #define TT this.blkdiscard
 #endif
-#define FLAG_z (1<<0)
-#define FLAG_s (1<<1)
-#define FLAG_o (1<<2)
-#define FLAG_l (1<<3)
-#define FLAG_f (1<<4)
+#define FLAG_z (1LL<<0)
+#define FLAG_s (1LL<<1)
+#define FLAG_o (1LL<<2)
+#define FLAG_l (1LL<<3)
+#define FLAG_f (1LL<<4)
 #endif
 
 #ifdef FOR_blkid
@@ -3849,9 +3971,10 @@
 #ifndef TT
 #define TT this.blkid
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_L (1<<1)
-#define FLAG_U (1<<2)
+#define FLAG_s (1LL<<0)
+#define FLAG_o (1LL<<1)
+#define FLAG_L (1LL<<2)
+#define FLAG_U (1LL<<3)
 #endif
 
 #ifdef FOR_blockdev
@@ -3859,19 +3982,19 @@
 #ifndef TT
 #define TT this.blockdev
 #endif
-#define FLAG_rereadpt (1<<0)
-#define FLAG_flushbufs (1<<1)
-#define FLAG_setra (1<<2)
-#define FLAG_getra (1<<3)
-#define FLAG_getsize64 (1<<4)
-#define FLAG_getsize (1<<5)
-#define FLAG_getsz (1<<6)
-#define FLAG_setbsz (1<<7)
-#define FLAG_getbsz (1<<8)
-#define FLAG_getss (1<<9)
-#define FLAG_getro (1<<10)
-#define FLAG_setrw (1<<11)
-#define FLAG_setro (1<<12)
+#define FLAG_rereadpt (1LL<<0)
+#define FLAG_flushbufs (1LL<<1)
+#define FLAG_setra (1LL<<2)
+#define FLAG_getra (1LL<<3)
+#define FLAG_getsize64 (1LL<<4)
+#define FLAG_getsize (1LL<<5)
+#define FLAG_getsz (1LL<<6)
+#define FLAG_setbsz (1LL<<7)
+#define FLAG_getbsz (1LL<<8)
+#define FLAG_getss (1LL<<9)
+#define FLAG_getro (1LL<<10)
+#define FLAG_setrw (1LL<<11)
+#define FLAG_setro (1LL<<12)
 #endif
 
 #ifdef FOR_bootchartd
@@ -3912,7 +4035,7 @@
 #ifndef TT
 #define TT this.cal
 #endif
-#define FLAG_h (1<<0)
+#define FLAG_h (1LL<<0)
 #endif
 
 #ifdef FOR_cat
@@ -3920,20 +4043,10 @@
 #ifndef TT
 #define TT this.cat
 #endif
-#define FLAG_e (1<<0)
-#define FLAG_t (1<<1)
-#define FLAG_v (1<<2)
-#define FLAG_u (1<<3)
-#endif
-
-#ifdef FOR_catv
-#define CLEANUP_catv
-#ifndef TT
-#define TT this.catv
-#endif
-#define FLAG_e (FORCED_FLAG<<0)
-#define FLAG_t (FORCED_FLAG<<1)
-#define FLAG_v (FORCED_FLAG<<2)
+#define FLAG_e (1LL<<0)
+#define FLAG_t (1LL<<1)
+#define FLAG_v (1LL<<2)
+#define FLAG_u (1LL<<3)
 #endif
 
 #ifdef FOR_cd
@@ -3950,9 +4063,9 @@
 #ifndef TT
 #define TT this.chattr
 #endif
-#define FLAG_R (1<<0)
-#define FLAG_v (1<<1)
-#define FLAG_p (1<<2)
+#define FLAG_R (1LL<<0)
+#define FLAG_v (1LL<<1)
+#define FLAG_p (1LL<<2)
 #endif
 
 #ifdef FOR_chcon
@@ -3960,9 +4073,9 @@
 #ifndef TT
 #define TT this.chcon
 #endif
-#define FLAG_R (1<<0)
-#define FLAG_v (1<<1)
-#define FLAG_h (1<<2)
+#define FLAG_R (1LL<<0)
+#define FLAG_v (1LL<<1)
+#define FLAG_h (1LL<<2)
 #endif
 
 #ifdef FOR_chgrp
@@ -3970,13 +4083,13 @@
 #ifndef TT
 #define TT this.chgrp
 #endif
-#define FLAG_v (1<<0)
-#define FLAG_f (1<<1)
-#define FLAG_R (1<<2)
-#define FLAG_H (1<<3)
-#define FLAG_L (1<<4)
-#define FLAG_P (1<<5)
-#define FLAG_h (1<<6)
+#define FLAG_v (1LL<<0)
+#define FLAG_f (1LL<<1)
+#define FLAG_R (1LL<<2)
+#define FLAG_H (1LL<<3)
+#define FLAG_L (1LL<<4)
+#define FLAG_P (1LL<<5)
+#define FLAG_h (1LL<<6)
 #endif
 
 #ifdef FOR_chmod
@@ -3984,9 +4097,9 @@
 #ifndef TT
 #define TT this.chmod
 #endif
-#define FLAG_R (1<<0)
-#define FLAG_f (1<<1)
-#define FLAG_v (1<<2)
+#define FLAG_R (1LL<<0)
+#define FLAG_f (1LL<<1)
+#define FLAG_v (1LL<<2)
 #endif
 
 #ifdef FOR_chroot
@@ -4001,14 +4114,14 @@
 #ifndef TT
 #define TT this.chrt
 #endif
-#define FLAG_o (1<<0)
-#define FLAG_f (1<<1)
-#define FLAG_r (1<<2)
-#define FLAG_b (1<<3)
-#define FLAG_R (1<<4)
-#define FLAG_i (1<<5)
-#define FLAG_p (1<<6)
-#define FLAG_m (1<<7)
+#define FLAG_o (1LL<<0)
+#define FLAG_f (1LL<<1)
+#define FLAG_r (1LL<<2)
+#define FLAG_b (1LL<<3)
+#define FLAG_R (1LL<<4)
+#define FLAG_i (1LL<<5)
+#define FLAG_p (1LL<<6)
+#define FLAG_m (1LL<<7)
 #endif
 
 #ifdef FOR_chsh
@@ -4031,11 +4144,11 @@
 #ifndef TT
 #define TT this.cksum
 #endif
-#define FLAG_N (1<<0)
-#define FLAG_L (1<<1)
-#define FLAG_P (1<<2)
-#define FLAG_I (1<<3)
-#define FLAG_H (1<<4)
+#define FLAG_N (1LL<<0)
+#define FLAG_L (1LL<<1)
+#define FLAG_P (1LL<<2)
+#define FLAG_I (1LL<<3)
+#define FLAG_H (1LL<<4)
 #endif
 
 #ifdef FOR_clear
@@ -4050,9 +4163,9 @@
 #ifndef TT
 #define TT this.cmp
 #endif
-#define FLAG_n (1<<0)
-#define FLAG_s (1<<1)
-#define FLAG_l (1<<2)
+#define FLAG_n (1LL<<0)
+#define FLAG_s (1LL<<1)
+#define FLAG_l (1LL<<2)
 #endif
 
 #ifdef FOR_comm
@@ -4060,9 +4173,9 @@
 #ifndef TT
 #define TT this.comm
 #endif
-#define FLAG_1 (1<<0)
-#define FLAG_2 (1<<1)
-#define FLAG_3 (1<<2)
+#define FLAG_1 (1LL<<0)
+#define FLAG_2 (1LL<<1)
+#define FLAG_3 (1LL<<2)
 #endif
 
 #ifdef FOR_count
@@ -4077,26 +4190,26 @@
 #ifndef TT
 #define TT this.cp
 #endif
-#define FLAG_T (1<<0)
-#define FLAG_t (1<<1)
-#define FLAG_i (1<<2)
-#define FLAG_f (1<<3)
-#define FLAG_F (1<<4)
-#define FLAG_n (1<<5)
-#define FLAG_v (1<<6)
-#define FLAG_l (1<<7)
-#define FLAG_s (1<<8)
-#define FLAG_a (1<<9)
-#define FLAG_d (1<<10)
-#define FLAG_u (1<<11)
-#define FLAG_r (1<<12)
-#define FLAG_p (1<<13)
-#define FLAG_P (1<<14)
-#define FLAG_L (1<<15)
-#define FLAG_H (1<<16)
-#define FLAG_R (1<<17)
-#define FLAG_D (1<<18)
-#define FLAG_preserve (1<<19)
+#define FLAG_T (1LL<<0)
+#define FLAG_t (1LL<<1)
+#define FLAG_i (1LL<<2)
+#define FLAG_f (1LL<<3)
+#define FLAG_F (1LL<<4)
+#define FLAG_n (1LL<<5)
+#define FLAG_v (1LL<<6)
+#define FLAG_l (1LL<<7)
+#define FLAG_s (1LL<<8)
+#define FLAG_a (1LL<<9)
+#define FLAG_d (1LL<<10)
+#define FLAG_u (1LL<<11)
+#define FLAG_r (1LL<<12)
+#define FLAG_p (1LL<<13)
+#define FLAG_P (1LL<<14)
+#define FLAG_L (1LL<<15)
+#define FLAG_H (1LL<<16)
+#define FLAG_R (1LL<<17)
+#define FLAG_D (1LL<<18)
+#define FLAG_preserve (1LL<<19)
 #endif
 
 #ifdef FOR_cpio
@@ -4104,20 +4217,21 @@
 #ifndef TT
 #define TT this.cpio
 #endif
-#define FLAG_o (1<<0)
-#define FLAG_v (1<<1)
-#define FLAG_F (1<<2)
-#define FLAG_t (1<<3)
-#define FLAG_i (1<<4)
-#define FLAG_p (1<<5)
-#define FLAG_H (1<<6)
-#define FLAG_u (1<<7)
-#define FLAG_d (1<<8)
-#define FLAG_m (1<<9)
-#define FLAG_no_preserve_owner (1<<10)
-#define FLAG_quiet (1<<11)
-#define FLAG_renumber_inodes (1<<12)
-#define FLAG_ignore_devno (1<<13)
+#define FLAG_o (1LL<<0)
+#define FLAG_v (1LL<<1)
+#define FLAG_F (1LL<<2)
+#define FLAG_t (1LL<<3)
+#define FLAG_i (1LL<<4)
+#define FLAG_p (1LL<<5)
+#define FLAG_H (1LL<<6)
+#define FLAG_u (1LL<<7)
+#define FLAG_d (1LL<<8)
+#define FLAG_m (1LL<<9)
+#define FLAG_R (1LL<<10)
+#define FLAG_no_preserve_owner (1LL<<11)
+#define FLAG_quiet (1LL<<12)
+#define FLAG_renumber_inodes (1LL<<13)
+#define FLAG_ignore_devno (1LL<<14)
 #endif
 
 #ifdef FOR_crc32
@@ -4158,16 +4272,16 @@
 #ifndef TT
 #define TT this.cut
 #endif
-#define FLAG_n (1<<0)
-#define FLAG_D (1<<1)
-#define FLAG_s (1<<2)
-#define FLAG_d (1<<3)
-#define FLAG_O (1<<4)
-#define FLAG_C (1<<5)
-#define FLAG_F (1<<6)
-#define FLAG_f (1<<7)
-#define FLAG_c (1<<8)
-#define FLAG_b (1<<9)
+#define FLAG_n (1LL<<0)
+#define FLAG_D (1LL<<1)
+#define FLAG_s (1LL<<2)
+#define FLAG_d (1LL<<3)
+#define FLAG_O (1LL<<4)
+#define FLAG_C (1LL<<5)
+#define FLAG_F (1LL<<6)
+#define FLAG_f (1LL<<7)
+#define FLAG_c (1LL<<8)
+#define FLAG_b (1LL<<9)
 #endif
 
 #ifdef FOR_date
@@ -4175,12 +4289,12 @@
 #ifndef TT
 #define TT this.date
 #endif
-#define FLAG_u (1<<0)
-#define FLAG_s (1<<1)
-#define FLAG_r (1<<2)
-#define FLAG_I (1<<3)
-#define FLAG_D (1<<4)
-#define FLAG_d (1<<5)
+#define FLAG_u (1LL<<0)
+#define FLAG_s (1LL<<1)
+#define FLAG_r (1LL<<2)
+#define FLAG_I (1LL<<3)
+#define FLAG_D (1LL<<4)
+#define FLAG_d (1LL<<5)
 #endif
 
 #ifdef FOR_dd
@@ -4249,27 +4363,27 @@
 #define FLAG_C (FORCED_FLAG<<28)
 #define FLAG_D (FORCED_FLAG<<29)
 #define FLAG_E (FORCED_FLAG<<30)
-#define FLAG_F (FORCED_FLAGLL<<31)
-#define FLAG_G (FORCED_FLAGLL<<32)
-#define FLAG_H (FORCED_FLAGLL<<33)
-#define FLAG_I (FORCED_FLAGLL<<34)
-#define FLAG_J (FORCED_FLAGLL<<35)
-#define FLAG_K (FORCED_FLAGLL<<36)
-#define FLAG_L (FORCED_FLAGLL<<37)
-#define FLAG_M (FORCED_FLAGLL<<38)
-#define FLAG_N (FORCED_FLAGLL<<39)
-#define FLAG_O (FORCED_FLAGLL<<40)
-#define FLAG_P (FORCED_FLAGLL<<41)
-#define FLAG_Q (FORCED_FLAGLL<<42)
-#define FLAG_R (FORCED_FLAGLL<<43)
-#define FLAG_S (FORCED_FLAGLL<<44)
-#define FLAG_T (FORCED_FLAGLL<<45)
-#define FLAG_U (FORCED_FLAGLL<<46)
-#define FLAG_V (FORCED_FLAGLL<<47)
-#define FLAG_W (FORCED_FLAGLL<<48)
-#define FLAG_X (FORCED_FLAGLL<<49)
-#define FLAG_Y (FORCED_FLAGLL<<50)
-#define FLAG_Z (FORCED_FLAGLL<<51)
+#define FLAG_F (FORCED_FLAG<<31)
+#define FLAG_G (FORCED_FLAG<<32)
+#define FLAG_H (FORCED_FLAG<<33)
+#define FLAG_I (FORCED_FLAG<<34)
+#define FLAG_J (FORCED_FLAG<<35)
+#define FLAG_K (FORCED_FLAG<<36)
+#define FLAG_L (FORCED_FLAG<<37)
+#define FLAG_M (FORCED_FLAG<<38)
+#define FLAG_N (FORCED_FLAG<<39)
+#define FLAG_O (FORCED_FLAG<<40)
+#define FLAG_P (FORCED_FLAG<<41)
+#define FLAG_Q (FORCED_FLAG<<42)
+#define FLAG_R (FORCED_FLAG<<43)
+#define FLAG_S (FORCED_FLAG<<44)
+#define FLAG_T (FORCED_FLAG<<45)
+#define FLAG_U (FORCED_FLAG<<46)
+#define FLAG_V (FORCED_FLAG<<47)
+#define FLAG_W (FORCED_FLAG<<48)
+#define FLAG_X (FORCED_FLAG<<49)
+#define FLAG_Y (FORCED_FLAG<<50)
+#define FLAG_Z (FORCED_FLAG<<51)
 #endif
 
 #ifdef FOR_demo_number
@@ -4312,13 +4426,13 @@
 #ifndef TT
 #define TT this.df
 #endif
-#define FLAG_a (1<<0)
-#define FLAG_t (1<<1)
-#define FLAG_i (1<<2)
-#define FLAG_h (1<<3)
-#define FLAG_k (1<<4)
-#define FLAG_P (1<<5)
-#define FLAG_H (1<<6)
+#define FLAG_a (1LL<<0)
+#define FLAG_t (1LL<<1)
+#define FLAG_i (1LL<<2)
+#define FLAG_h (1LL<<3)
+#define FLAG_k (1LL<<4)
+#define FLAG_P (1LL<<5)
+#define FLAG_H (1LL<<6)
 #endif
 
 #ifdef FOR_dhcp
@@ -4390,24 +4504,28 @@
 #ifndef TT
 #define TT this.diff
 #endif
-#define FLAG_U (1<<0)
-#define FLAG_r (1<<1)
-#define FLAG_N (1<<2)
-#define FLAG_S (1<<3)
-#define FLAG_L (1<<4)
-#define FLAG_a (1<<5)
-#define FLAG_q (1<<6)
-#define FLAG_s (1<<7)
-#define FLAG_T (1<<8)
-#define FLAG_i (1<<9)
-#define FLAG_w (1<<10)
-#define FLAG_t (1<<11)
-#define FLAG_u (1<<12)
-#define FLAG_b (1<<13)
-#define FLAG_d (1<<14)
-#define FLAG_B (1<<15)
-#define FLAG_strip_trailing_cr (1<<16)
-#define FLAG_color (1<<17)
+#define FLAG_U (1LL<<0)
+#define FLAG_r (1LL<<1)
+#define FLAG_N (1LL<<2)
+#define FLAG_L (1LL<<3)
+#define FLAG_F (1LL<<4)
+#define FLAG_S (1LL<<5)
+#define FLAG_a (1LL<<6)
+#define FLAG_q (1LL<<7)
+#define FLAG_s (1LL<<8)
+#define FLAG_T (1LL<<9)
+#define FLAG_i (1LL<<10)
+#define FLAG_w (1LL<<11)
+#define FLAG_t (1LL<<12)
+#define FLAG_u (1LL<<13)
+#define FLAG_b (1LL<<14)
+#define FLAG_d (1LL<<15)
+#define FLAG_B (1LL<<16)
+#define FLAG_strip_trailing_cr (1LL<<17)
+#define FLAG_color (1LL<<18)
+#define FLAG_new_line_format (1LL<<19)
+#define FLAG_old_line_format (1LL<<20)
+#define FLAG_unchanged_line_format (1LL<<21)
 #endif
 
 #ifdef FOR_dirname
@@ -4422,15 +4540,15 @@
 #ifndef TT
 #define TT this.dmesg
 #endif
-#define FLAG_c (1<<0)
-#define FLAG_n (1<<1)
-#define FLAG_s (1<<2)
-#define FLAG_r (1<<3)
-#define FLAG_t (1<<4)
-#define FLAG_T (1<<5)
-#define FLAG_S (1<<6)
-#define FLAG_C (1<<7)
-#define FLAG_w (1<<8)
+#define FLAG_c (1LL<<0)
+#define FLAG_n (1LL<<1)
+#define FLAG_s (1LL<<2)
+#define FLAG_r (1LL<<3)
+#define FLAG_t (1LL<<4)
+#define FLAG_T (1LL<<5)
+#define FLAG_S (1LL<<6)
+#define FLAG_C (1LL<<7)
+#define FLAG_w (1LL<<8)
 #endif
 
 #ifdef FOR_dnsdomainname
@@ -4452,19 +4570,19 @@
 #ifndef TT
 #define TT this.du
 #endif
-#define FLAG_b (1<<0)
-#define FLAG_x (1<<1)
-#define FLAG_s (1<<2)
-#define FLAG_L (1<<3)
-#define FLAG_K (1<<4)
-#define FLAG_k (1<<5)
-#define FLAG_H (1<<6)
-#define FLAG_a (1<<7)
-#define FLAG_c (1<<8)
-#define FLAG_l (1<<9)
-#define FLAG_m (1<<10)
-#define FLAG_h (1<<11)
-#define FLAG_d (1<<12)
+#define FLAG_b (1LL<<0)
+#define FLAG_x (1LL<<1)
+#define FLAG_s (1LL<<2)
+#define FLAG_L (1LL<<3)
+#define FLAG_K (1LL<<4)
+#define FLAG_k (1LL<<5)
+#define FLAG_H (1LL<<6)
+#define FLAG_a (1LL<<7)
+#define FLAG_c (1LL<<8)
+#define FLAG_l (1LL<<9)
+#define FLAG_m (1LL<<10)
+#define FLAG_h (1LL<<11)
+#define FLAG_d (1LL<<12)
 #endif
 
 #ifdef FOR_dumpleases
@@ -4482,9 +4600,9 @@
 #ifndef TT
 #define TT this.echo
 #endif
-#define FLAG_n (1<<0)
-#define FLAG_e (1<<1)
-#define FLAG_E (1<<2)
+#define FLAG_n (1LL<<0)
+#define FLAG_e (1LL<<1)
+#define FLAG_E (1LL<<2)
 #endif
 
 #ifdef FOR_eject
@@ -4502,9 +4620,9 @@
 #ifndef TT
 #define TT this.env
 #endif
-#define FLAG_u (1<<0)
-#define FLAG_0 (1<<1)
-#define FLAG_i (1<<2)
+#define FLAG_u (1LL<<0)
+#define FLAG_0 (1LL<<1)
+#define FLAG_i (1LL<<2)
 #endif
 
 #ifdef FOR_eval
@@ -4536,7 +4654,7 @@
 #ifndef TT
 #define TT this.expand
 #endif
-#define FLAG_t (1<<0)
+#define FLAG_t (1LL<<0)
 #endif
 
 #ifdef FOR_export
@@ -4560,6 +4678,8 @@
 #ifndef TT
 #define TT this.factor
 #endif
+#define FLAG_x (FORCED_FLAG<<0)
+#define FLAG_h (FORCED_FLAG<<1)
 #endif
 
 #ifdef FOR_fallocate
@@ -4567,8 +4687,8 @@
 #ifndef TT
 #define TT this.fallocate
 #endif
-#define FLAG_o (1<<0)
-#define FLAG_l (1<<1)
+#define FLAG_o (1LL<<0)
+#define FLAG_l (1LL<<1)
 #endif
 
 #ifdef FOR_false
@@ -4596,10 +4716,10 @@
 #ifndef TT
 #define TT this.file
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_L (1<<1)
-#define FLAG_h (1<<2)
-#define FLAG_b (1<<3)
+#define FLAG_s (1LL<<0)
+#define FLAG_L (1LL<<1)
+#define FLAG_h (1LL<<2)
+#define FLAG_b (1LL<<3)
 #endif
 
 #ifdef FOR_find
@@ -4607,8 +4727,8 @@
 #ifndef TT
 #define TT this.find
 #endif
-#define FLAG_L (1<<0)
-#define FLAG_H (1<<1)
+#define FLAG_L (1LL<<0)
+#define FLAG_H (1LL<<1)
 #endif
 
 #ifdef FOR_flock
@@ -4616,10 +4736,10 @@
 #ifndef TT
 #define TT this.flock
 #endif
-#define FLAG_x (1<<0)
-#define FLAG_u (1<<1)
-#define FLAG_s (1<<2)
-#define FLAG_n (1<<3)
+#define FLAG_x (1LL<<0)
+#define FLAG_u (1LL<<1)
+#define FLAG_s (1LL<<2)
+#define FLAG_n (1LL<<3)
 #endif
 
 #ifdef FOR_fmt
@@ -4627,7 +4747,7 @@
 #ifndef TT
 #define TT this.fmt
 #endif
-#define FLAG_w (1<<0)
+#define FLAG_w (1LL<<0)
 #endif
 
 #ifdef FOR_fold
@@ -4646,11 +4766,11 @@
 #ifndef TT
 #define TT this.free
 #endif
-#define FLAG_b (1<<0)
-#define FLAG_k (1<<1)
-#define FLAG_m (1<<2)
-#define FLAG_g (1<<3)
-#define FLAG_h (1<<4)
+#define FLAG_b (1LL<<0)
+#define FLAG_k (1LL<<1)
+#define FLAG_m (1LL<<2)
+#define FLAG_g (1LL<<3)
+#define FLAG_h (1LL<<4)
 #endif
 
 #ifdef FOR_freeramdisk
@@ -4681,8 +4801,8 @@
 #ifndef TT
 #define TT this.fsfreeze
 #endif
-#define FLAG_u (1<<0)
-#define FLAG_f (1<<1)
+#define FLAG_u (1LL<<0)
+#define FLAG_f (1LL<<1)
 #endif
 
 #ifdef FOR_fstype
@@ -4697,7 +4817,7 @@
 #ifndef TT
 #define TT this.fsync
 #endif
-#define FLAG_d (1<<0)
+#define FLAG_d (1LL<<0)
 #endif
 
 #ifdef FOR_ftpget
@@ -4725,8 +4845,8 @@
 #ifndef TT
 #define TT this.getconf
 #endif
-#define FLAG_l (1<<0)
-#define FLAG_a (1<<1)
+#define FLAG_l (1LL<<0)
+#define FLAG_a (1LL<<1)
 #endif
 
 #ifdef FOR_getenforce
@@ -4741,10 +4861,10 @@
 #ifndef TT
 #define TT this.getfattr
 #endif
-#define FLAG_n (1<<0)
-#define FLAG_h (1<<1)
-#define FLAG_d (1<<2)
-#define FLAG_only_values (1<<3)
+#define FLAG_n (1LL<<0)
+#define FLAG_h (1LL<<1)
+#define FLAG_d (1LL<<2)
+#define FLAG_only_values (1LL<<3)
 #endif
 
 #ifdef FOR_getopt
@@ -4752,12 +4872,12 @@
 #ifndef TT
 #define TT this.getopt
 #endif
-#define FLAG_u (1<<0)
-#define FLAG_T (1<<1)
-#define FLAG_l (1<<2)
-#define FLAG_o (1<<3)
-#define FLAG_n (1<<4)
-#define FLAG_a (1<<5)
+#define FLAG_u (1LL<<0)
+#define FLAG_T (1LL<<1)
+#define FLAG_l (1LL<<2)
+#define FLAG_o (1LL<<3)
+#define FLAG_n (1LL<<4)
+#define FLAG_a (1LL<<5)
 #endif
 
 #ifdef FOR_getty
@@ -4778,6 +4898,41 @@
 #define FLAG_t (FORCED_FLAG<<10)
 #endif
 
+#ifdef FOR_gitcheckout
+#define CLEANUP_gitcheckout
+#ifndef TT
+#define TT this.gitcheckout
+#endif
+#endif
+
+#ifdef FOR_gitclone
+#define CLEANUP_gitclone
+#ifndef TT
+#define TT this.gitclone
+#endif
+#endif
+
+#ifdef FOR_gitfetch
+#define CLEANUP_gitfetch
+#ifndef TT
+#define TT this.gitfetch
+#endif
+#endif
+
+#ifdef FOR_gitinit
+#define CLEANUP_gitinit
+#ifndef TT
+#define TT this.gitinit
+#endif
+#endif
+
+#ifdef FOR_gitremote
+#define CLEANUP_gitremote
+#ifndef TT
+#define TT this.gitremote
+#endif
+#endif
+
 #ifdef FOR_gpiodetect
 #define CLEANUP_gpiodetect
 #ifndef TT
@@ -4820,37 +4975,37 @@
 #ifndef TT
 #define TT this.grep
 #endif
-#define FLAG_x (1<<0)
-#define FLAG_m (1<<1)
-#define FLAG_A (1<<2)
-#define FLAG_B (1<<3)
-#define FLAG_C (1<<4)
-#define FLAG_f (1<<5)
-#define FLAG_e (1<<6)
-#define FLAG_q (1<<7)
-#define FLAG_l (1<<8)
-#define FLAG_L (1<<9)
-#define FLAG_c (1<<10)
-#define FLAG_w (1<<11)
-#define FLAG_v (1<<12)
-#define FLAG_s (1<<13)
-#define FLAG_R (1<<14)
-#define FLAG_r (1<<15)
-#define FLAG_o (1<<16)
-#define FLAG_n (1<<17)
-#define FLAG_i (1<<18)
-#define FLAG_h (1<<19)
-#define FLAG_b (1<<20)
-#define FLAG_a (1<<21)
-#define FLAG_I (1<<22)
-#define FLAG_H (1<<23)
-#define FLAG_F (1<<24)
-#define FLAG_E (1<<25)
-#define FLAG_z (1<<26)
-#define FLAG_Z (1<<27)
-#define FLAG_M (1<<28)
-#define FLAG_S (1<<29)
-#define FLAG_exclude_dir (1<<30)
+#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
@@ -4883,19 +5038,20 @@
 #ifndef TT
 #define TT this.gunzip
 #endif
-#define FLAG_9 (1<<0)
-#define FLAG_8 (1<<1)
-#define FLAG_7 (1<<2)
-#define FLAG_6 (1<<3)
-#define FLAG_5 (1<<4)
-#define FLAG_4 (1<<5)
-#define FLAG_3 (1<<6)
-#define FLAG_2 (1<<7)
-#define FLAG_1 (1<<8)
-#define FLAG_k (1<<9)
-#define FLAG_f (1<<10)
-#define FLAG_d (1<<11)
-#define FLAG_c (1<<12)
+#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)
 #endif
 
 #ifdef FOR_gzip
@@ -4903,20 +5059,21 @@
 #ifndef TT
 #define TT this.gzip
 #endif
-#define FLAG_9 (1<<0)
-#define FLAG_8 (1<<1)
-#define FLAG_7 (1<<2)
-#define FLAG_6 (1<<3)
-#define FLAG_5 (1<<4)
-#define FLAG_4 (1<<5)
-#define FLAG_3 (1<<6)
-#define FLAG_2 (1<<7)
-#define FLAG_1 (1<<8)
-#define FLAG_k (1<<9)
-#define FLAG_f (1<<10)
-#define FLAG_d (1<<11)
-#define FLAG_c (1<<12)
-#define FLAG_n (1<<13)
+#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
@@ -4924,10 +5081,10 @@
 #ifndef TT
 #define TT this.head
 #endif
-#define FLAG_v (1<<0)
-#define FLAG_q (1<<1)
-#define FLAG_c (1<<2)
-#define FLAG_n (1<<3)
+#define FLAG_v (1LL<<0)
+#define FLAG_q (1LL<<1)
+#define FLAG_c (1LL<<2)
+#define FLAG_n (1LL<<3)
 #endif
 
 #ifdef FOR_hello
@@ -4942,9 +5099,9 @@
 #ifndef TT
 #define TT this.help
 #endif
-#define FLAG_u (1<<0)
-#define FLAG_h (1<<1)
-#define FLAG_a (1<<2)
+#define FLAG_u (1LL<<0)
+#define FLAG_h (1LL<<1)
+#define FLAG_a (1LL<<2)
 #endif
 
 #ifdef FOR_hexdump
@@ -4993,11 +5150,19 @@
 #ifndef TT
 #define TT this.hostname
 #endif
-#define FLAG_F (1<<0)
-#define FLAG_f (1<<1)
-#define FLAG_s (1<<2)
-#define FLAG_d (1<<3)
-#define FLAG_b (1<<4)
+#define FLAG_F (1LL<<0)
+#define FLAG_f (1LL<<1)
+#define FLAG_s (1LL<<2)
+#define FLAG_d (1LL<<3)
+#define FLAG_b (1LL<<4)
+#endif
+
+#ifdef FOR_httpd
+#define CLEANUP_httpd
+#ifndef TT
+#define TT this.httpd
+#endif
+#define FLAG_v (FORCED_FLAG<<0)
 #endif
 
 #ifdef FOR_hwclock
@@ -5005,14 +5170,14 @@
 #ifndef TT
 #define TT this.hwclock
 #endif
-#define FLAG_w (1<<0)
-#define FLAG_r (1<<1)
-#define FLAG_s (1<<2)
-#define FLAG_t (1<<3)
-#define FLAG_l (1<<4)
-#define FLAG_u (1<<5)
-#define FLAG_f (1<<6)
-#define FLAG_fast (1<<7)
+#define FLAG_w (1LL<<0)
+#define FLAG_r (1LL<<1)
+#define FLAG_s (1LL<<2)
+#define FLAG_t (1LL<<3)
+#define FLAG_l (1LL<<4)
+#define FLAG_u (1LL<<5)
+#define FLAG_f (1LL<<6)
+#define FLAG_fast (1LL<<7)
 #endif
 
 #ifdef FOR_i2cdetect
@@ -5020,12 +5185,12 @@
 #ifndef TT
 #define TT this.i2cdetect
 #endif
-#define FLAG_y (1<<0)
-#define FLAG_r (1<<1)
-#define FLAG_q (1<<2)
-#define FLAG_l (1<<3)
-#define FLAG_F (1<<4)
-#define FLAG_a (1<<5)
+#define FLAG_y (1LL<<0)
+#define FLAG_r (1LL<<1)
+#define FLAG_q (1LL<<2)
+#define FLAG_l (1LL<<3)
+#define FLAG_F (1LL<<4)
+#define FLAG_a (1LL<<5)
 #endif
 
 #ifdef FOR_i2cdump
@@ -5033,8 +5198,8 @@
 #ifndef TT
 #define TT this.i2cdump
 #endif
-#define FLAG_y (1<<0)
-#define FLAG_f (1<<1)
+#define FLAG_y (1LL<<0)
+#define FLAG_f (1LL<<1)
 #endif
 
 #ifdef FOR_i2cget
@@ -5042,8 +5207,8 @@
 #ifndef TT
 #define TT this.i2cget
 #endif
-#define FLAG_y (1<<0)
-#define FLAG_f (1<<1)
+#define FLAG_y (1LL<<0)
+#define FLAG_f (1LL<<1)
 #endif
 
 #ifdef FOR_i2cset
@@ -5051,8 +5216,8 @@
 #ifndef TT
 #define TT this.i2cset
 #endif
-#define FLAG_y (1<<0)
-#define FLAG_f (1<<1)
+#define FLAG_y (1LL<<0)
+#define FLAG_f (1LL<<1)
 #endif
 
 #ifdef FOR_iconv
@@ -5060,10 +5225,10 @@
 #ifndef TT
 #define TT this.iconv
 #endif
-#define FLAG_f (1<<0)
-#define FLAG_t (1<<1)
-#define FLAG_s (1<<2)
-#define FLAG_c (1<<3)
+#define FLAG_f (1LL<<0)
+#define FLAG_t (1LL<<1)
+#define FLAG_s (1LL<<2)
+#define FLAG_c (1LL<<3)
 #endif
 
 #ifdef FOR_id
@@ -5071,12 +5236,12 @@
 #ifndef TT
 #define TT this.id
 #endif
-#define FLAG_u (1<<0)
-#define FLAG_r (1<<1)
-#define FLAG_g (1<<2)
-#define FLAG_G (1<<3)
-#define FLAG_n (1<<4)
-#define FLAG_Z (1<<5)
+#define FLAG_u (1LL<<0)
+#define FLAG_r (1LL<<1)
+#define FLAG_g (1LL<<2)
+#define FLAG_G (1LL<<3)
+#define FLAG_n (1LL<<4)
+#define FLAG_Z (1LL<<5)
 #endif
 
 #ifdef FOR_ifconfig
@@ -5084,8 +5249,8 @@
 #ifndef TT
 #define TT this.ifconfig
 #endif
-#define FLAG_S (1<<0)
-#define FLAG_a (1<<1)
+#define FLAG_S (1LL<<0)
+#define FLAG_a (1LL<<1)
 #endif
 
 #ifdef FOR_init
@@ -5114,16 +5279,16 @@
 #ifndef TT
 #define TT this.install
 #endif
-#define FLAG_g (1<<0)
-#define FLAG_o (1<<1)
-#define FLAG_m (1<<2)
-#define FLAG_t (1<<3)
-#define FLAG_v (1<<4)
-#define FLAG_s (1<<5)
-#define FLAG_p (1<<6)
-#define FLAG_D (1<<7)
-#define FLAG_d (1<<8)
-#define FLAG_c (1<<9)
+#define FLAG_g (1LL<<0)
+#define FLAG_o (1LL<<1)
+#define FLAG_m (1LL<<2)
+#define FLAG_t (1LL<<3)
+#define FLAG_v (1LL<<4)
+#define FLAG_s (1LL<<5)
+#define FLAG_p (1LL<<6)
+#define FLAG_D (1LL<<7)
+#define FLAG_d (1LL<<8)
+#define FLAG_c (1LL<<9)
 #endif
 
 #ifdef FOR_ionice
@@ -5131,10 +5296,10 @@
 #ifndef TT
 #define TT this.ionice
 #endif
-#define FLAG_p (1<<0)
-#define FLAG_n (1<<1)
-#define FLAG_c (1<<2)
-#define FLAG_t (1<<3)
+#define FLAG_p (1LL<<0)
+#define FLAG_n (1LL<<1)
+#define FLAG_c (1LL<<2)
+#define FLAG_t (1LL<<3)
 #endif
 
 #ifdef FOR_iorenice
@@ -5149,21 +5314,21 @@
 #ifndef TT
 #define TT this.iotop
 #endif
-#define FLAG_q (1<<0)
-#define FLAG_b (1<<1)
-#define FLAG_n (1<<2)
-#define FLAG_m (1<<3)
-#define FLAG_d (1<<4)
-#define FLAG_s (1<<5)
-#define FLAG_u (1<<6)
-#define FLAG_p (1<<7)
-#define FLAG_o (1<<8)
-#define FLAG_k (1<<9)
-#define FLAG_H (1<<10)
-#define FLAG_O (1<<11)
-#define FLAG_K (1<<12)
-#define FLAG_a (1<<13)
-#define FLAG_A (1<<14)
+#define FLAG_q (1LL<<0)
+#define FLAG_b (1LL<<1)
+#define FLAG_n (1LL<<2)
+#define FLAG_m (1LL<<3)
+#define FLAG_d (1LL<<4)
+#define FLAG_s (1LL<<5)
+#define FLAG_u (1LL<<6)
+#define FLAG_p (1LL<<7)
+#define FLAG_o (1LL<<8)
+#define FLAG_k (1LL<<9)
+#define FLAG_H (1LL<<10)
+#define FLAG_O (1LL<<11)
+#define FLAG_K (1LL<<12)
+#define FLAG_a (1LL<<13)
+#define FLAG_A (1LL<<14)
 #endif
 
 #ifdef FOR_ip
@@ -5220,8 +5385,8 @@
 #ifndef TT
 #define TT this.kill
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_l (1<<1)
+#define FLAG_s (1LL<<0)
+#define FLAG_l (1LL<<1)
 #endif
 
 #ifdef FOR_killall
@@ -5229,12 +5394,12 @@
 #ifndef TT
 #define TT this.killall
 #endif
-#define FLAG_w (1<<0)
-#define FLAG_v (1<<1)
-#define FLAG_q (1<<2)
-#define FLAG_l (1<<3)
-#define FLAG_i (1<<4)
-#define FLAG_s (1<<5)
+#define FLAG_w (1LL<<0)
+#define FLAG_v (1LL<<1)
+#define FLAG_q (1LL<<2)
+#define FLAG_l (1LL<<3)
+#define FLAG_i (1LL<<4)
+#define FLAG_s (1LL<<5)
 #endif
 
 #ifdef FOR_killall5
@@ -5284,13 +5449,13 @@
 #ifndef TT
 #define TT this.ln
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_f (1<<1)
-#define FLAG_n (1<<2)
-#define FLAG_v (1<<3)
-#define FLAG_T (1<<4)
-#define FLAG_t (1<<5)
-#define FLAG_r (1<<6)
+#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_load_policy
@@ -5305,8 +5470,8 @@
 #ifndef TT
 #define TT this.log
 #endif
-#define FLAG_t (1<<0)
-#define FLAG_p (1<<1)
+#define FLAG_t (1LL<<0)
+#define FLAG_p (1LL<<1)
 #endif
 
 #ifdef FOR_logger
@@ -5314,9 +5479,9 @@
 #ifndef TT
 #define TT this.logger
 #endif
-#define FLAG_s (FORCED_FLAG<<0)
-#define FLAG_p (FORCED_FLAG<<1)
-#define FLAG_t (FORCED_FLAG<<2)
+#define FLAG_s (1LL<<0)
+#define FLAG_p (1LL<<1)
+#define FLAG_t (1LL<<2)
 #endif
 
 #ifdef FOR_login
@@ -5348,16 +5513,16 @@
 #ifndef TT
 #define TT this.losetup
 #endif
-#define FLAG_D (1<<0)
-#define FLAG_a (1<<1)
-#define FLAG_c (1<<2)
-#define FLAG_d (1<<3)
-#define FLAG_f (1<<4)
-#define FLAG_j (1<<5)
-#define FLAG_o (1<<6)
-#define FLAG_r (1<<7)
-#define FLAG_s (1<<8)
-#define FLAG_S (1<<9)
+#define FLAG_D (1LL<<0)
+#define FLAG_a (1LL<<1)
+#define FLAG_c (1LL<<2)
+#define FLAG_d (1LL<<3)
+#define FLAG_f (1LL<<4)
+#define FLAG_j (1LL<<5)
+#define FLAG_o (1LL<<6)
+#define FLAG_r (1LL<<7)
+#define FLAG_s (1LL<<8)
+#define FLAG_S (1LL<<9)
 #endif
 
 #ifdef FOR_ls
@@ -5365,39 +5530,45 @@
 #ifndef TT
 #define TT this.ls
 #endif
-#define FLAG_1 (1<<0)
-#define FLAG_x (1<<1)
-#define FLAG_w (1<<2)
-#define FLAG_u (1<<3)
-#define FLAG_t (1<<4)
-#define FLAG_s (1<<5)
-#define FLAG_r (1<<6)
-#define FLAG_q (1<<7)
-#define FLAG_p (1<<8)
-#define FLAG_n (1<<9)
-#define FLAG_m (1<<10)
-#define FLAG_l (1<<11)
-#define FLAG_k (1<<12)
-#define FLAG_i (1<<13)
-#define FLAG_h (1<<14)
-#define FLAG_f (1<<15)
-#define FLAG_d (1<<16)
-#define FLAG_c (1<<17)
-#define FLAG_b (1<<18)
-#define FLAG_a (1<<19)
-#define FLAG_S (1<<20)
-#define FLAG_R (1<<21)
-#define FLAG_L (1<<22)
-#define FLAG_H (1<<23)
-#define FLAG_F (1<<24)
-#define FLAG_C (1<<25)
-#define FLAG_A (1<<26)
-#define FLAG_o (1<<27)
-#define FLAG_g (1<<28)
-#define FLAG_Z (1<<29)
-#define FLAG_show_control_chars (1<<30)
-#define FLAG_full_time (1LL<<31)
-#define FLAG_color (1LL<<32)
+#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_show_control_chars (1LL<<35)
+#define FLAG_full_time (1LL<<36)
+#define FLAG_color (1LL<<37)
+#define FLAG_sort (1LL<<38)
 #endif
 
 #ifdef FOR_lsattr
@@ -5405,12 +5576,12 @@
 #ifndef TT
 #define TT this.lsattr
 #endif
-#define FLAG_R (1<<0)
-#define FLAG_v (1<<1)
-#define FLAG_p (1<<2)
-#define FLAG_a (1<<3)
-#define FLAG_d (1<<4)
-#define FLAG_l (1<<5)
+#define FLAG_R (1LL<<0)
+#define FLAG_v (1LL<<1)
+#define FLAG_p (1LL<<2)
+#define FLAG_a (1LL<<3)
+#define FLAG_d (1LL<<4)
+#define FLAG_l (1LL<<5)
 #endif
 
 #ifdef FOR_lsmod
@@ -5425,9 +5596,9 @@
 #ifndef TT
 #define TT this.lsof
 #endif
-#define FLAG_t (1<<0)
-#define FLAG_p (1<<1)
-#define FLAG_l (1<<2)
+#define FLAG_t (1LL<<0)
+#define FLAG_p (1LL<<1)
+#define FLAG_l (1LL<<2)
 #endif
 
 #ifdef FOR_lspci
@@ -5435,11 +5606,12 @@
 #ifndef TT
 #define TT this.lspci
 #endif
-#define FLAG_i (1<<0)
-#define FLAG_n (1<<1)
-#define FLAG_k (1<<2)
-#define FLAG_m (1<<3)
-#define FLAG_e (1<<4)
+#define FLAG_i (1LL<<0)
+#define FLAG_x (1LL<<1)
+#define FLAG_n (1LL<<2)
+#define FLAG_k (1LL<<3)
+#define FLAG_m (1LL<<4)
+#define FLAG_e (1LL<<5)
 #endif
 
 #ifdef FOR_lsusb
@@ -5447,7 +5619,7 @@
 #ifndef TT
 #define TT this.lsusb
 #endif
-#define FLAG_i (1<<0)
+#define FLAG_i (1LL<<0)
 #endif
 
 #ifdef FOR_makedevs
@@ -5455,7 +5627,7 @@
 #ifndef TT
 #define TT this.makedevs
 #endif
-#define FLAG_d (1<<0)
+#define FLAG_d (1LL<<0)
 #endif
 
 #ifdef FOR_man
@@ -5481,9 +5653,9 @@
 #ifndef TT
 #define TT this.md5sum
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_c (1<<1)
-#define FLAG_b (1<<2)
+#define FLAG_s (1LL<<0)
+#define FLAG_c (1LL<<1)
+#define FLAG_b (1LL<<2)
 #endif
 
 #ifdef FOR_mdev
@@ -5499,8 +5671,8 @@
 #ifndef TT
 #define TT this.microcom
 #endif
-#define FLAG_X (1<<0)
-#define FLAG_s (1<<1)
+#define FLAG_X (1LL<<0)
+#define FLAG_s (1LL<<1)
 #endif
 
 #ifdef FOR_mix
@@ -5519,10 +5691,10 @@
 #ifndef TT
 #define TT this.mkdir
 #endif
-#define FLAG_m (1<<0)
-#define FLAG_p (1<<1)
-#define FLAG_v (1<<2)
-#define FLAG_Z (1<<3)
+#define FLAG_m (1LL<<0)
+#define FLAG_p (1LL<<1)
+#define FLAG_v (1LL<<2)
+#define FLAG_Z (1LL<<3)
 #endif
 
 #ifdef FOR_mke2fs
@@ -5545,8 +5717,8 @@
 #ifndef TT
 #define TT this.mkfifo
 #endif
-#define FLAG_m (1<<0)
-#define FLAG_Z (1<<1)
+#define FLAG_m (1LL<<0)
+#define FLAG_Z (1LL<<1)
 #endif
 
 #ifdef FOR_mknod
@@ -5554,8 +5726,8 @@
 #ifndef TT
 #define TT this.mknod
 #endif
-#define FLAG_Z (1<<0)
-#define FLAG_m (1<<1)
+#define FLAG_Z (1LL<<0)
+#define FLAG_m (1LL<<1)
 #endif
 
 #ifdef FOR_mkpasswd
@@ -5573,7 +5745,7 @@
 #ifndef TT
 #define TT this.mkswap
 #endif
-#define FLAG_L (1<<0)
+#define FLAG_L (1LL<<0)
 #endif
 
 #ifdef FOR_mktemp
@@ -5581,12 +5753,12 @@
 #ifndef TT
 #define TT this.mktemp
 #endif
-#define FLAG_t (1<<0)
-#define FLAG_p (1<<1)
-#define FLAG_d (1<<2)
-#define FLAG_q (1<<3)
-#define FLAG_u (1<<4)
-#define FLAG_tmpdir (1<<5)
+#define FLAG_t (1LL<<0)
+#define FLAG_p (1LL<<1)
+#define FLAG_d (1LL<<2)
+#define FLAG_q (1LL<<3)
+#define FLAG_u (1LL<<4)
+#define FLAG_tmpdir (1LL<<5)
 #endif
 
 #ifdef FOR_modinfo
@@ -5594,10 +5766,10 @@
 #ifndef TT
 #define TT this.modinfo
 #endif
-#define FLAG_0 (1<<0)
-#define FLAG_F (1<<1)
-#define FLAG_k (1<<2)
-#define FLAG_b (1<<3)
+#define FLAG_0 (1LL<<0)
+#define FLAG_F (1LL<<1)
+#define FLAG_k (1LL<<2)
+#define FLAG_b (1LL<<3)
 #endif
 
 #ifdef FOR_modprobe
@@ -5605,15 +5777,15 @@
 #ifndef TT
 #define TT this.modprobe
 #endif
-#define FLAG_d (1<<0)
-#define FLAG_b (1<<1)
-#define FLAG_D (1<<2)
-#define FLAG_s (1<<3)
-#define FLAG_v (1<<4)
-#define FLAG_q (1<<5)
-#define FLAG_r (1<<6)
-#define FLAG_l (1<<7)
-#define FLAG_a (1<<8)
+#define FLAG_d (1LL<<0)
+#define FLAG_b (1LL<<1)
+#define FLAG_D (1LL<<2)
+#define FLAG_s (1LL<<3)
+#define FLAG_v (1LL<<4)
+#define FLAG_q (1LL<<5)
+#define FLAG_r (1LL<<6)
+#define FLAG_l (1LL<<7)
+#define FLAG_a (1LL<<8)
 #endif
 
 #ifdef FOR_more
@@ -5628,15 +5800,16 @@
 #ifndef TT
 #define TT this.mount
 #endif
-#define FLAG_o (1<<0)
-#define FLAG_t (1<<1)
-#define FLAG_w (1<<2)
-#define FLAG_v (1<<3)
-#define FLAG_r (1<<4)
-#define FLAG_n (1<<5)
-#define FLAG_f (1<<6)
-#define FLAG_a (1<<7)
-#define FLAG_O (1<<8)
+#define FLAG_o (1LL<<0)
+#define FLAG_t (1LL<<1)
+#define FLAG_w (1LL<<2)
+#define FLAG_v (1LL<<3)
+#define FLAG_r (1LL<<4)
+#define FLAG_n (1LL<<5)
+#define FLAG_f (1LL<<6)
+#define FLAG_a (1LL<<7)
+#define FLAG_O (1LL<<8)
+#define FLAG_R (1LL<<9)
 #endif
 
 #ifdef FOR_mountpoint
@@ -5644,9 +5817,9 @@
 #ifndef TT
 #define TT this.mountpoint
 #endif
-#define FLAG_x (1<<0)
-#define FLAG_d (1<<1)
-#define FLAG_q (1<<2)
+#define FLAG_x (1LL<<0)
+#define FLAG_d (1LL<<1)
+#define FLAG_q (1LL<<2)
 #endif
 
 #ifdef FOR_mv
@@ -5654,13 +5827,13 @@
 #ifndef TT
 #define TT this.mv
 #endif
-#define FLAG_T (1<<0)
-#define FLAG_t (1<<1)
-#define FLAG_i (1<<2)
-#define FLAG_f (1<<3)
-#define FLAG_F (1<<4)
-#define FLAG_n (1<<5)
-#define FLAG_v (1<<6)
+#define FLAG_T (1LL<<0)
+#define FLAG_t (1LL<<1)
+#define FLAG_i (1LL<<2)
+#define FLAG_f (1LL<<3)
+#define FLAG_F (1LL<<4)
+#define FLAG_n (1LL<<5)
+#define FLAG_v (1LL<<6)
 #endif
 
 #ifdef FOR_nbd_client
@@ -5668,8 +5841,17 @@
 #ifndef TT
 #define TT this.nbd_client
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_n (1<<1)
+#define FLAG_s (1LL<<0)
+#define FLAG_n (1LL<<1)
+#define FLAG_b (1LL<<2)
+#endif
+
+#ifdef FOR_nbd_server
+#define CLEANUP_nbd_server
+#ifndef TT
+#define TT this.nbd_server
+#endif
+#define FLAG_r (FORCED_FLAG<<0)
 #endif
 
 #ifdef FOR_netcat
@@ -5677,20 +5859,21 @@
 #ifndef TT
 #define TT this.netcat
 #endif
-#define FLAG_U (1<<0)
-#define FLAG_u (1<<1)
-#define FLAG_6 (1<<2)
-#define FLAG_4 (1<<3)
-#define FLAG_f (1<<4)
-#define FLAG_s (1<<5)
-#define FLAG_q (1<<6)
-#define FLAG_p (1<<7)
-#define FLAG_W (1<<8)
-#define FLAG_w (1<<9)
-#define FLAG_L (1<<10)
-#define FLAG_l (1<<11)
-#define FLAG_E (1<<12)
-#define FLAG_t (1<<13)
+#define FLAG_n (1LL<<0)
+#define FLAG_U (1LL<<1)
+#define FLAG_u (1LL<<2)
+#define FLAG_6 (1LL<<3)
+#define FLAG_4 (1LL<<4)
+#define FLAG_f (1LL<<5)
+#define FLAG_s (1LL<<6)
+#define FLAG_q (1LL<<7)
+#define FLAG_p (1LL<<8)
+#define FLAG_W (1LL<<9)
+#define FLAG_w (1LL<<10)
+#define FLAG_L (1LL<<11)
+#define FLAG_l (1LL<<12)
+#define FLAG_E (1LL<<13)
+#define FLAG_t (1LL<<14)
 #endif
 
 #ifdef FOR_netstat
@@ -5698,17 +5881,17 @@
 #ifndef TT
 #define TT this.netstat
 #endif
-#define FLAG_l (1<<0)
-#define FLAG_a (1<<1)
-#define FLAG_e (1<<2)
-#define FLAG_n (1<<3)
-#define FLAG_t (1<<4)
-#define FLAG_u (1<<5)
-#define FLAG_w (1<<6)
-#define FLAG_x (1<<7)
-#define FLAG_r (1<<8)
-#define FLAG_W (1<<9)
-#define FLAG_p (1<<10)
+#define FLAG_l (1LL<<0)
+#define FLAG_a (1LL<<1)
+#define FLAG_e (1LL<<2)
+#define FLAG_n (1LL<<3)
+#define FLAG_t (1LL<<4)
+#define FLAG_u (1LL<<5)
+#define FLAG_w (1LL<<6)
+#define FLAG_x (1LL<<7)
+#define FLAG_r (1LL<<8)
+#define FLAG_W (1LL<<9)
+#define FLAG_p (1LL<<10)
 #endif
 
 #ifdef FOR_nice
@@ -5716,7 +5899,7 @@
 #ifndef TT
 #define TT this.nice
 #endif
-#define FLAG_n (1<<0)
+#define FLAG_n (1LL<<0)
 #endif
 
 #ifdef FOR_nl
@@ -5724,13 +5907,13 @@
 #ifndef TT
 #define TT this.nl
 #endif
-#define FLAG_E (1<<0)
-#define FLAG_s (1<<1)
-#define FLAG_n (1<<2)
-#define FLAG_b (1<<3)
-#define FLAG_w (1<<4)
-#define FLAG_l (1<<5)
-#define FLAG_v (1<<6)
+#define FLAG_E (1LL<<0)
+#define FLAG_s (1LL<<1)
+#define FLAG_n (1LL<<2)
+#define FLAG_b (1LL<<3)
+#define FLAG_w (1LL<<4)
+#define FLAG_l (1LL<<5)
+#define FLAG_v (1LL<<6)
 #endif
 
 #ifdef FOR_nohup
@@ -5745,7 +5928,7 @@
 #ifndef TT
 #define TT this.nproc
 #endif
-#define FLAG_all (1<<0)
+#define FLAG_all (1LL<<0)
 #endif
 
 #ifdef FOR_nsenter
@@ -5753,14 +5936,16 @@
 #ifndef TT
 #define TT this.nsenter
 #endif
-#define FLAG_U (1<<0)
-#define FLAG_u (1<<1)
-#define FLAG_p (1<<2)
-#define FLAG_n (1<<3)
-#define FLAG_m (1<<4)
-#define FLAG_i (1<<5)
-#define FLAG_t (1<<6)
-#define FLAG_F (1<<7)
+#define FLAG_U (1LL<<0)
+#define FLAG_u (1LL<<1)
+#define FLAG_p (1LL<<2)
+#define FLAG_n (1LL<<3)
+#define FLAG_m (1LL<<4)
+#define FLAG_i (1LL<<5)
+#define FLAG_C (1LL<<6)
+#define FLAG_t (1LL<<7)
+#define FLAG_F (1LL<<8)
+#define FLAG_a (1LL<<9)
 #endif
 
 #ifdef FOR_od
@@ -5768,18 +5953,18 @@
 #ifndef TT
 #define TT this.od
 #endif
-#define FLAG_t (1<<0)
-#define FLAG_A (1<<1)
-#define FLAG_b (1<<2)
-#define FLAG_c (1<<3)
-#define FLAG_d (1<<4)
-#define FLAG_o (1<<5)
-#define FLAG_s (1<<6)
-#define FLAG_x (1<<7)
-#define FLAG_N (1<<8)
-#define FLAG_w (1<<9)
-#define FLAG_v (1<<10)
-#define FLAG_j (1<<11)
+#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_oneit
@@ -5826,8 +6011,8 @@
 #ifndef TT
 #define TT this.paste
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_d (1<<1)
+#define FLAG_s (1LL<<0)
+#define FLAG_d (1LL<<1)
 #endif
 
 #ifdef FOR_patch
@@ -5835,19 +6020,19 @@
 #ifndef TT
 #define TT this.patch
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_R (1<<1)
-#define FLAG_i (1<<2)
-#define FLAG_d (1<<3)
-#define FLAG_p (1<<4)
-#define FLAG_l (1<<5)
-#define FLAG_u (1<<6)
-#define FLAG_f (1<<7)
-#define FLAG_g (1<<8)
-#define FLAG_F (1<<9)
+#define FLAG_s (1LL<<0)
+#define FLAG_R (1LL<<1)
+#define FLAG_i (1LL<<2)
+#define FLAG_d (1LL<<3)
+#define FLAG_p (1LL<<4)
+#define FLAG_l (1LL<<5)
+#define FLAG_u (1LL<<6)
+#define FLAG_f (1LL<<7)
+#define FLAG_g (1LL<<8)
+#define FLAG_F (1LL<<9)
 #define FLAG_x (FORCED_FLAG<<10)
-#define FLAG_dry_run (1<<11)
-#define FLAG_no_backup_if_mismatch (1<<12)
+#define FLAG_dry_run (1LL<<11)
+#define FLAG_no_backup_if_mismatch (1LL<<12)
 #endif
 
 #ifdef FOR_pgrep
@@ -5855,22 +6040,22 @@
 #ifndef TT
 #define TT this.pgrep
 #endif
-#define FLAG_L (1<<0)
-#define FLAG_x (1<<1)
-#define FLAG_v (1<<2)
-#define FLAG_o (1<<3)
-#define FLAG_n (1<<4)
-#define FLAG_f (1<<5)
-#define FLAG_G (1<<6)
-#define FLAG_g (1<<7)
-#define FLAG_P (1<<8)
-#define FLAG_s (1<<9)
-#define FLAG_t (1<<10)
-#define FLAG_U (1<<11)
-#define FLAG_u (1<<12)
-#define FLAG_d (1<<13)
-#define FLAG_l (1<<14)
-#define FLAG_c (1<<15)
+#define FLAG_L (1LL<<0)
+#define FLAG_x (1LL<<1)
+#define FLAG_v (1LL<<2)
+#define FLAG_o (1LL<<3)
+#define FLAG_n (1LL<<4)
+#define FLAG_f (1LL<<5)
+#define FLAG_G (1LL<<6)
+#define FLAG_g (1LL<<7)
+#define FLAG_P (1LL<<8)
+#define FLAG_s (1LL<<9)
+#define FLAG_t (1LL<<10)
+#define FLAG_U (1LL<<11)
+#define FLAG_u (1LL<<12)
+#define FLAG_d (1LL<<13)
+#define FLAG_l (1LL<<14)
+#define FLAG_c (1LL<<15)
 #endif
 
 #ifdef FOR_pidof
@@ -5878,9 +6063,9 @@
 #ifndef TT
 #define TT this.pidof
 #endif
-#define FLAG_x (1<<0)
-#define FLAG_o (1<<1)
-#define FLAG_s (1<<2)
+#define FLAG_x (1LL<<0)
+#define FLAG_o (1LL<<1)
+#define FLAG_s (1LL<<2)
 #endif
 
 #ifdef FOR_ping
@@ -5888,18 +6073,18 @@
 #ifndef TT
 #define TT this.ping
 #endif
-#define FLAG_I (1<<0)
-#define FLAG_6 (1<<1)
-#define FLAG_4 (1<<2)
-#define FLAG_f (1<<3)
-#define FLAG_q (1<<4)
-#define FLAG_w (1<<5)
-#define FLAG_W (1<<6)
-#define FLAG_i (1<<7)
-#define FLAG_s (1<<8)
-#define FLAG_c (1<<9)
-#define FLAG_t (1<<10)
-#define FLAG_m (1<<11)
+#define FLAG_I (1LL<<0)
+#define FLAG_6 (1LL<<1)
+#define FLAG_4 (1LL<<2)
+#define FLAG_f (1LL<<3)
+#define FLAG_q (1LL<<4)
+#define FLAG_w (1LL<<5)
+#define FLAG_W (1LL<<6)
+#define FLAG_i (1LL<<7)
+#define FLAG_s (1LL<<8)
+#define FLAG_c (1LL<<9)
+#define FLAG_t (1LL<<10)
+#define FLAG_m (1LL<<11)
 #endif
 
 #ifdef FOR_pivot_root
@@ -5914,20 +6099,20 @@
 #ifndef TT
 #define TT this.pkill
 #endif
-#define FLAG_l (1<<0)
-#define FLAG_x (1<<1)
-#define FLAG_v (1<<2)
-#define FLAG_o (1<<3)
-#define FLAG_n (1<<4)
-#define FLAG_f (1<<5)
-#define FLAG_G (1<<6)
-#define FLAG_g (1<<7)
-#define FLAG_P (1<<8)
-#define FLAG_s (1<<9)
-#define FLAG_t (1<<10)
-#define FLAG_U (1<<11)
-#define FLAG_u (1<<12)
-#define FLAG_V (1<<13)
+#define FLAG_l (1LL<<0)
+#define FLAG_x (1LL<<1)
+#define FLAG_v (1LL<<2)
+#define FLAG_o (1LL<<3)
+#define FLAG_n (1LL<<4)
+#define FLAG_f (1LL<<5)
+#define FLAG_G (1LL<<6)
+#define FLAG_g (1LL<<7)
+#define FLAG_P (1LL<<8)
+#define FLAG_s (1LL<<9)
+#define FLAG_t (1LL<<10)
+#define FLAG_U (1LL<<11)
+#define FLAG_u (1LL<<12)
+#define FLAG_V (1LL<<13)
 #endif
 
 #ifdef FOR_pmap
@@ -5935,9 +6120,9 @@
 #ifndef TT
 #define TT this.pmap
 #endif
-#define FLAG_x (1<<0)
-#define FLAG_q (1<<1)
-#define FLAG_p (1<<2)
+#define FLAG_x (1LL<<0)
+#define FLAG_q (1LL<<1)
+#define FLAG_p (1LL<<2)
 #endif
 
 #ifdef FOR_printenv
@@ -5945,8 +6130,8 @@
 #ifndef TT
 #define TT this.printenv
 #endif
-#define FLAG_0 (1<<0)
-#define FLAG_null (1<<1)
+#define FLAG_0 (1LL<<0)
+#define FLAG_null (1LL<<1)
 #endif
 
 #ifdef FOR_printf
@@ -5961,28 +6146,28 @@
 #ifndef TT
 #define TT this.ps
 #endif
-#define FLAG_Z (1<<0)
-#define FLAG_w (1<<1)
-#define FLAG_G (1<<2)
-#define FLAG_g (1<<3)
-#define FLAG_U (1<<4)
-#define FLAG_u (1<<5)
-#define FLAG_T (1<<6)
-#define FLAG_t (1<<7)
-#define FLAG_s (1<<8)
-#define FLAG_p (1<<9)
-#define FLAG_O (1<<10)
-#define FLAG_o (1<<11)
-#define FLAG_n (1<<12)
-#define FLAG_M (1<<13)
-#define FLAG_l (1<<14)
-#define FLAG_f (1<<15)
-#define FLAG_e (1<<16)
-#define FLAG_d (1<<17)
-#define FLAG_A (1<<18)
-#define FLAG_a (1<<19)
-#define FLAG_P (1<<20)
-#define FLAG_k (1<<21)
+#define FLAG_Z (1LL<<0)
+#define FLAG_w (1LL<<1)
+#define FLAG_G (1LL<<2)
+#define FLAG_g (1LL<<3)
+#define FLAG_U (1LL<<4)
+#define FLAG_u (1LL<<5)
+#define FLAG_T (1LL<<6)
+#define FLAG_t (1LL<<7)
+#define FLAG_s (1LL<<8)
+#define FLAG_p (1LL<<9)
+#define FLAG_O (1LL<<10)
+#define FLAG_o (1LL<<11)
+#define FLAG_n (1LL<<12)
+#define FLAG_M (1LL<<13)
+#define FLAG_l (1LL<<14)
+#define FLAG_f (1LL<<15)
+#define FLAG_e (1LL<<16)
+#define FLAG_d (1LL<<17)
+#define FLAG_A (1LL<<18)
+#define FLAG_a (1LL<<19)
+#define FLAG_P (1LL<<20)
+#define FLAG_k (1LL<<21)
 #endif
 
 #ifdef FOR_pwd
@@ -5990,8 +6175,8 @@
 #ifndef TT
 #define TT this.pwd
 #endif
-#define FLAG_P (1<<0)
-#define FLAG_L (1<<1)
+#define FLAG_P (1LL<<0)
+#define FLAG_L (1LL<<1)
 #endif
 
 #ifdef FOR_pwdx
@@ -5999,7 +6184,7 @@
 #ifndef TT
 #define TT this.pwdx
 #endif
-#define FLAG_a (1<<0)
+#define FLAG_a (1LL<<0)
 #endif
 
 #ifdef FOR_pwgen
@@ -6033,18 +6218,18 @@
 #ifndef TT
 #define TT this.readelf
 #endif
-#define FLAG_x (1<<0)
-#define FLAG_W (1<<1)
-#define FLAG_s (1<<2)
-#define FLAG_S (1<<3)
-#define FLAG_p (1<<4)
-#define FLAG_n (1<<5)
-#define FLAG_l (1<<6)
-#define FLAG_h (1<<7)
-#define FLAG_e (1<<8)
-#define FLAG_d (1<<9)
-#define FLAG_a (1<<10)
-#define FLAG_dyn_syms (1<<11)
+#define FLAG_x (1LL<<0)
+#define FLAG_W (1LL<<1)
+#define FLAG_s (1LL<<2)
+#define FLAG_S (1LL<<3)
+#define FLAG_p (1LL<<4)
+#define FLAG_n (1LL<<5)
+#define FLAG_l (1LL<<6)
+#define FLAG_h (1LL<<7)
+#define FLAG_e (1LL<<8)
+#define FLAG_d (1LL<<9)
+#define FLAG_a (1LL<<10)
+#define FLAG_dyn_syms (1LL<<11)
 #endif
 
 #ifdef FOR_readlink
@@ -6052,11 +6237,29 @@
 #ifndef TT
 #define TT this.readlink
 #endif
-#define FLAG_f (1<<0)
-#define FLAG_e (1<<1)
-#define FLAG_m (1<<2)
-#define FLAG_q (1<<3)
-#define FLAG_n (1<<4)
+#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 (1LL<<0)
+#define FLAG_q (1LL<<1)
+#define FLAG_m (1LL<<2)
+#define FLAG_e (1LL<<3)
+#define FLAG_P (1LL<<4)
+#define FLAG_L (1LL<<5)
+#define FLAG_s (1LL<<6)
+#define FLAG_R (1LL<<7)
+#define FLAG_relative_base (1LL<<8)
 #endif
 
 #ifdef FOR_reboot
@@ -6074,10 +6277,10 @@
 #ifndef TT
 #define TT this.renice
 #endif
-#define FLAG_n (1<<0)
-#define FLAG_u (1<<1)
-#define FLAG_p (1<<2)
-#define FLAG_g (1<<3)
+#define FLAG_n (1LL<<0)
+#define FLAG_u (1LL<<1)
+#define FLAG_p (1LL<<2)
+#define FLAG_g (1LL<<3)
 #endif
 
 #ifdef FOR_reset
@@ -6092,12 +6295,12 @@
 #ifndef TT
 #define TT this.restorecon
 #endif
-#define FLAG_v (1<<0)
-#define FLAG_r (1<<1)
-#define FLAG_R (1<<2)
-#define FLAG_n (1<<3)
-#define FLAG_F (1<<4)
-#define FLAG_D (1<<5)
+#define FLAG_v (1LL<<0)
+#define FLAG_r (1LL<<1)
+#define FLAG_R (1LL<<2)
+#define FLAG_n (1LL<<3)
+#define FLAG_F (1LL<<4)
+#define FLAG_D (1LL<<5)
 #endif
 
 #ifdef FOR_rev
@@ -6119,11 +6322,11 @@
 #ifndef TT
 #define TT this.rm
 #endif
-#define FLAG_v (1<<0)
-#define FLAG_r (1<<1)
-#define FLAG_R (1<<2)
-#define FLAG_i (1<<3)
-#define FLAG_f (1<<4)
+#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_rmdir
@@ -6131,8 +6334,8 @@
 #ifndef TT
 #define TT this.rmdir
 #endif
-#define FLAG_p (1<<0)
-#define FLAG_ignore_fail_on_non_empty (1<<1)
+#define FLAG_p (1LL<<0)
+#define FLAG_ignore_fail_on_non_empty (1LL<<1)
 #endif
 
 #ifdef FOR_rmmod
@@ -6140,8 +6343,8 @@
 #ifndef TT
 #define TT this.rmmod
 #endif
-#define FLAG_f (1<<0)
-#define FLAG_w (1<<1)
+#define FLAG_f (1LL<<0)
+#define FLAG_w (1LL<<1)
 #endif
 
 #ifdef FOR_route
@@ -6159,16 +6362,16 @@
 #ifndef TT
 #define TT this.rtcwake
 #endif
-#define FLAG_v (1<<0)
-#define FLAG_u (1<<1)
-#define FLAG_t (1<<2)
-#define FLAG_s (1<<3)
-#define FLAG_m (1<<4)
-#define FLAG_l (1<<5)
-#define FLAG_d (1<<6)
-#define FLAG_a (1<<7)
-#define FLAG_auto (1<<8)
-#define FLAG_list_modes (1<<9)
+#define FLAG_v (1LL<<0)
+#define FLAG_u (1LL<<1)
+#define FLAG_t (1LL<<2)
+#define FLAG_s (1LL<<3)
+#define FLAG_m (1LL<<4)
+#define FLAG_l (1LL<<5)
+#define FLAG_d (1LL<<6)
+#define FLAG_a (1LL<<7)
+#define FLAG_auto (1LL<<8)
+#define FLAG_list_modes (1LL<<9)
 #endif
 
 #ifdef FOR_runcon
@@ -6183,16 +6386,17 @@
 #ifndef TT
 #define TT this.sed
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_z (1<<1)
-#define FLAG_r (1<<2)
-#define FLAG_E (1<<3)
-#define FLAG_n (1<<4)
-#define FLAG_i (1<<5)
-#define FLAG_f (1<<6)
-#define FLAG_e (1<<7)
-#define FLAG_version (1<<8)
-#define FLAG_help (1<<9)
+#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_sendevent
@@ -6207,9 +6411,9 @@
 #ifndef TT
 #define TT this.seq
 #endif
-#define FLAG_w (1<<0)
-#define FLAG_s (1<<1)
-#define FLAG_f (1<<2)
+#define FLAG_w (1LL<<0)
+#define FLAG_s (1LL<<1)
+#define FLAG_f (1LL<<2)
 #endif
 
 #ifdef FOR_set
@@ -6231,10 +6435,10 @@
 #ifndef TT
 #define TT this.setfattr
 #endif
-#define FLAG_x (1<<0)
-#define FLAG_v (1<<1)
-#define FLAG_n (1<<2)
-#define FLAG_h (1<<3)
+#define FLAG_x (1LL<<0)
+#define FLAG_v (1LL<<1)
+#define FLAG_n (1LL<<2)
+#define FLAG_h (1LL<<3)
 #endif
 
 #ifdef FOR_setsid
@@ -6242,9 +6446,9 @@
 #ifndef TT
 #define TT this.setsid
 #endif
-#define FLAG_d (1<<0)
-#define FLAG_c (1<<1)
-#define FLAG_w (1<<2)
+#define FLAG_d (1LL<<0)
+#define FLAG_c (1LL<<1)
+#define FLAG_w (1LL<<2)
 #endif
 
 #ifdef FOR_sh
@@ -6291,6 +6495,16 @@
 #define FLAG_z (FORCED_FLAG<<6)
 #endif
 
+#ifdef FOR_shuf
+#define CLEANUP_shuf
+#ifndef TT
+#define TT this.shuf
+#endif
+#define FLAG_n (FORCED_FLAG<<0)
+#define FLAG_e (FORCED_FLAG<<1)
+#define FLAG_z (FORCED_FLAG<<2)
+#endif
+
 #ifdef FOR_skeleton
 #define CLEANUP_skeleton
 #ifndef TT
@@ -6301,9 +6515,12 @@
 #define FLAG_c (FORCED_FLAG<<2)
 #define FLAG_d (FORCED_FLAG<<3)
 #define FLAG_e (FORCED_FLAG<<4)
-#define FLAG_also (FORCED_FLAG<<5)
-#define FLAG_blubber (FORCED_FLAG<<6)
-#define FLAG_walrus (FORCED_FLAG<<7)
+#define FLAG_f (FORCED_FLAG<<5)
+#define FLAG_g (FORCED_FLAG<<6)
+#define FLAG_h (FORCED_FLAG<<7)
+#define FLAG_also (FORCED_FLAG<<8)
+#define FLAG_blubber (FORCED_FLAG<<9)
+#define FLAG_walrus (FORCED_FLAG<<10)
 #endif
 
 #ifdef FOR_skeleton_alias
@@ -6346,26 +6563,27 @@
 #ifndef TT
 #define TT this.sort
 #endif
-#define FLAG_n (1<<0)
-#define FLAG_u (1<<1)
-#define FLAG_r (1<<2)
-#define FLAG_i (1<<3)
-#define FLAG_f (1<<4)
-#define FLAG_d (1<<5)
-#define FLAG_z (1<<6)
-#define FLAG_s (1<<7)
-#define FLAG_c (1<<8)
-#define FLAG_M (1<<9)
-#define FLAG_b (1<<10)
-#define FLAG_V (1<<11)
-#define FLAG_x (1<<12)
-#define FLAG_t (1<<13)
-#define FLAG_k (1<<14)
-#define FLAG_o (1<<15)
-#define FLAG_m (1<<16)
-#define FLAG_T (1<<17)
-#define FLAG_S (1<<18)
-#define FLAG_g (1<<19)
+#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 (1LL<<20)
 #endif
 
 #ifdef FOR_source
@@ -6380,10 +6598,10 @@
 #ifndef TT
 #define TT this.split
 #endif
-#define FLAG_n (1<<0)
-#define FLAG_l (1<<1)
-#define FLAG_b (1<<2)
-#define FLAG_a (1<<3)
+#define FLAG_n (1LL<<0)
+#define FLAG_l (1LL<<1)
+#define FLAG_b (1LL<<2)
+#define FLAG_a (1LL<<3)
 #endif
 
 #ifdef FOR_stat
@@ -6391,10 +6609,10 @@
 #ifndef TT
 #define TT this.stat
 #endif
-#define FLAG_t (1<<0)
-#define FLAG_L (1<<1)
-#define FLAG_f (1<<2)
-#define FLAG_c (1<<3)
+#define FLAG_t (1LL<<0)
+#define FLAG_L (1LL<<1)
+#define FLAG_f (1LL<<2)
+#define FLAG_c (1LL<<3)
 #endif
 
 #ifdef FOR_strace
@@ -6412,11 +6630,11 @@
 #ifndef TT
 #define TT this.strings
 #endif
-#define FLAG_o (1<<0)
-#define FLAG_f (1<<1)
-#define FLAG_n (1<<2)
-#define FLAG_a (1<<3)
-#define FLAG_t (1<<4)
+#define FLAG_o (1LL<<0)
+#define FLAG_f (1LL<<1)
+#define FLAG_n (1LL<<2)
+#define FLAG_a (1LL<<3)
+#define FLAG_t (1LL<<4)
 #endif
 
 #ifdef FOR_stty
@@ -6424,9 +6642,9 @@
 #ifndef TT
 #define TT this.stty
 #endif
-#define FLAG_g (1<<0)
-#define FLAG_F (1<<1)
-#define FLAG_a (1<<2)
+#define FLAG_g (1LL<<0)
+#define FLAG_F (1LL<<1)
+#define FLAG_a (1LL<<2)
 #endif
 
 #ifdef FOR_su
@@ -6456,6 +6674,8 @@
 #ifndef TT
 #define TT this.swapoff
 #endif
+#define FLAG_v (1LL<<0)
+#define FLAG_a (1LL<<1)
 #endif
 
 #ifdef FOR_swapon
@@ -6463,8 +6683,8 @@
 #ifndef TT
 #define TT this.swapon
 #endif
-#define FLAG_d (1<<0)
-#define FLAG_p (1<<1)
+#define FLAG_d (1LL<<0)
+#define FLAG_p (1LL<<1)
 #endif
 
 #ifdef FOR_switch_root
@@ -6488,14 +6708,14 @@
 #ifndef TT
 #define TT this.sysctl
 #endif
-#define FLAG_A (1<<0)
-#define FLAG_a (1<<1)
-#define FLAG_p (1<<2)
-#define FLAG_w (1<<3)
-#define FLAG_q (1<<4)
-#define FLAG_N (1<<5)
-#define FLAG_e (1<<6)
-#define FLAG_n (1<<7)
+#define FLAG_A (1LL<<0)
+#define FLAG_a (1LL<<1)
+#define FLAG_p (1LL<<2)
+#define FLAG_w (1LL<<3)
+#define FLAG_q (1LL<<4)
+#define FLAG_N (1LL<<5)
+#define FLAG_e (1LL<<6)
+#define FLAG_n (1LL<<7)
 #endif
 
 #ifdef FOR_syslogd
@@ -6531,11 +6751,11 @@
 #ifndef TT
 #define TT this.tail
 #endif
-#define FLAG_n (1<<0)
-#define FLAG_c (1<<1)
-#define FLAG_s (1<<2)
-#define FLAG_F (1<<3)
-#define FLAG_f (1<<4)
+#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_tar
@@ -6543,41 +6763,54 @@
 #ifndef TT
 #define TT this.tar
 #endif
-#define FLAG_a (1<<0)
-#define FLAG_f (1<<1)
-#define FLAG_C (1<<2)
-#define FLAG_T (1<<3)
-#define FLAG_X (1<<4)
-#define FLAG_m (1<<5)
-#define FLAG_P (1<<6)
-#define FLAG_O (1<<7)
-#define FLAG_S (1<<8)
-#define FLAG_z (1<<9)
-#define FLAG_j (1<<10)
-#define FLAG_J (1<<11)
-#define FLAG_I (1<<12)
-#define FLAG_v (1<<13)
-#define FLAG_t (1<<14)
-#define FLAG_x (1<<15)
-#define FLAG_h (1<<16)
-#define FLAG_c (1<<17)
-#define FLAG_k (1<<18)
-#define FLAG_p (1<<19)
-#define FLAG_o (1<<20)
-#define FLAG_to_command (1<<21)
-#define FLAG_owner (1<<22)
-#define FLAG_group (1<<23)
-#define FLAG_mtime (1<<24)
-#define FLAG_mode (1<<25)
-#define FLAG_exclude (1<<26)
-#define FLAG_overwrite (1<<27)
-#define FLAG_no_same_permissions (1<<28)
-#define FLAG_numeric_owner (1<<29)
-#define FLAG_no_recursion (1<<30)
-#define FLAG_full_time (1LL<<31)
-#define FLAG_restrict (1LL<<32)
-#define FLAG_selinux (1LL<<33)
-#define FLAG_strip_components (1LL<<34)
+#define FLAG_s (1LL<<0)
+#define FLAG_a (1LL<<1)
+#define FLAG_f (1LL<<2)
+#define FLAG_C (1LL<<3)
+#define FLAG_I (1LL<<4)
+#define FLAG_T (1LL<<5)
+#define FLAG_X (1LL<<6)
+#define FLAG_m (1LL<<7)
+#define FLAG_P (1LL<<8)
+#define FLAG_O (1LL<<9)
+#define FLAG_S (1LL<<10)
+#define FLAG_z (1LL<<11)
+#define FLAG_j (1LL<<12)
+#define FLAG_J (1LL<<13)
+#define FLAG_v (1LL<<14)
+#define FLAG_t (1LL<<15)
+#define FLAG_x (1LL<<16)
+#define FLAG_h (1LL<<17)
+#define FLAG_c (1LL<<18)
+#define FLAG_k (1LL<<19)
+#define FLAG_p (1LL<<20)
+#define FLAG_o (1LL<<21)
+#define FLAG_xform (1LL<<22)
+#define FLAG_strip (1LL<<23)
+#define FLAG_to_command (1LL<<24)
+#define FLAG_owner (1LL<<25)
+#define FLAG_group (1LL<<26)
+#define FLAG_mtime (1LL<<27)
+#define FLAG_mode (1LL<<28)
+#define FLAG_sort (1LL<<29)
+#define FLAG_exclude (1LL<<30)
+#define FLAG_overwrite (1LL<<31)
+#define FLAG_no_same_permissions (1LL<<32)
+#define FLAG_numeric_owner (1LL<<33)
+#define FLAG_null (1LL<<34)
+#define FLAG_no_recursion (1LL<<35)
+#define FLAG_full_time (1LL<<36)
+#define FLAG_restrict (1LL<<37)
+#define FLAG_selinux (1LL<<38)
+#define FLAG_show_transformed_names (1LL<<39)
+#define FLAG_wildcards_match_slash (1LL<<40)
+#define FLAG_no_wildcards_match_slash (1LL<<41)
+#define FLAG_wildcards (1LL<<42)
+#define FLAG_no_wildcards (1LL<<43)
+#define FLAG_anchored (1LL<<44)
+#define FLAG_no_anchored (1LL<<45)
+#define FLAG_ignore_case (1LL<<46)
+#define FLAG_no_ignore_case (1LL<<47)
 #endif
 
 #ifdef FOR_taskset
@@ -6585,8 +6818,8 @@
 #ifndef TT
 #define TT this.taskset
 #endif
-#define FLAG_a (1<<0)
-#define FLAG_p (1<<1)
+#define FLAG_a (1LL<<0)
+#define FLAG_p (1LL<<1)
 #endif
 
 #ifdef FOR_tcpsvd
@@ -6599,8 +6832,8 @@
 #define FLAG_h (FORCED_FLAG<<2)
 #define FLAG_l (FORCED_FLAG<<3)
 #define FLAG_u (FORCED_FLAG<<4)
-#define FLAG_b (FORCED_FLAG<<5)
-#define FLAG_C (FORCED_FLAG<<6)
+#define FLAG_C (FORCED_FLAG<<5)
+#define FLAG_b (FORCED_FLAG<<6)
 #define FLAG_c (FORCED_FLAG<<7)
 #endif
 
@@ -6609,8 +6842,8 @@
 #ifndef TT
 #define TT this.tee
 #endif
-#define FLAG_a (1<<0)
-#define FLAG_i (1<<1)
+#define FLAG_a (1LL<<0)
+#define FLAG_i (1LL<<1)
 #endif
 
 #ifdef FOR_telnet
@@ -6671,8 +6904,8 @@
 #ifndef TT
 #define TT this.time
 #endif
-#define FLAG_v (1<<0)
-#define FLAG_p (1<<1)
+#define FLAG_v (1LL<<0)
+#define FLAG_p (1LL<<1)
 #endif
 
 #ifdef FOR_timeout
@@ -6680,11 +6913,12 @@
 #ifndef TT
 #define TT this.timeout
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_k (1<<1)
-#define FLAG_v (1<<2)
-#define FLAG_preserve_status (1<<3)
-#define FLAG_foreground (1<<4)
+#define FLAG_i (1LL<<0)
+#define FLAG_s (1LL<<1)
+#define FLAG_k (1LL<<2)
+#define FLAG_v (1LL<<3)
+#define FLAG_preserve_status (1LL<<4)
+#define FLAG_foreground (1LL<<5)
 #endif
 
 #ifdef FOR_top
@@ -6692,19 +6926,19 @@
 #ifndef TT
 #define TT this.top
 #endif
-#define FLAG_q (1<<0)
-#define FLAG_b (1<<1)
-#define FLAG_n (1<<2)
-#define FLAG_m (1<<3)
-#define FLAG_d (1<<4)
-#define FLAG_s (1<<5)
-#define FLAG_u (1<<6)
-#define FLAG_p (1<<7)
-#define FLAG_o (1<<8)
-#define FLAG_k (1<<9)
-#define FLAG_H (1<<10)
-#define FLAG_h (1<<11)
-#define FLAG_O (1<<12)
+#define FLAG_q (1LL<<0)
+#define FLAG_b (1LL<<1)
+#define FLAG_n (1LL<<2)
+#define FLAG_m (1LL<<3)
+#define FLAG_d (1LL<<4)
+#define FLAG_s (1LL<<5)
+#define FLAG_u (1LL<<6)
+#define FLAG_p (1LL<<7)
+#define FLAG_o (1LL<<8)
+#define FLAG_k (1LL<<9)
+#define FLAG_H (1LL<<10)
+#define FLAG_h (1LL<<11)
+#define FLAG_O (1LL<<12)
 #endif
 
 #ifdef FOR_touch
@@ -6712,14 +6946,14 @@
 #ifndef TT
 #define TT this.touch
 #endif
-#define FLAG_h (1<<0)
-#define FLAG_t (1<<1)
-#define FLAG_r (1<<2)
-#define FLAG_m (1<<3)
-#define FLAG_f (1<<4)
-#define FLAG_d (1<<5)
-#define FLAG_c (1<<6)
-#define FLAG_a (1<<7)
+#define FLAG_h (1LL<<0)
+#define FLAG_t (1LL<<1)
+#define FLAG_r (1LL<<2)
+#define FLAG_m (1LL<<3)
+#define FLAG_f (1LL<<4)
+#define FLAG_d (1LL<<5)
+#define FLAG_c (1LL<<6)
+#define FLAG_a (1LL<<7)
 #endif
 
 #ifdef FOR_toybox
@@ -6734,10 +6968,10 @@
 #ifndef TT
 #define TT this.tr
 #endif
-#define FLAG_d (1<<0)
-#define FLAG_s (1<<1)
-#define FLAG_c (1<<2)
-#define FLAG_C (1<<3)
+#define FLAG_d (1LL<<0)
+#define FLAG_s (1LL<<1)
+#define FLAG_c (1LL<<2)
+#define FLAG_C (1LL<<3)
 #endif
 
 #ifdef FOR_traceroute
@@ -6745,26 +6979,26 @@
 #ifndef TT
 #define TT this.traceroute
 #endif
-#define FLAG_4 (1<<0)
-#define FLAG_6 (1<<1)
-#define FLAG_F (1<<2)
-#define FLAG_U (1<<3)
-#define FLAG_I (1<<4)
-#define FLAG_l (1<<5)
-#define FLAG_d (1<<6)
-#define FLAG_n (1<<7)
-#define FLAG_v (1<<8)
-#define FLAG_r (1<<9)
-#define FLAG_m (1<<10)
-#define FLAG_p (1<<11)
-#define FLAG_q (1<<12)
-#define FLAG_s (1<<13)
-#define FLAG_t (1<<14)
-#define FLAG_w (1<<15)
-#define FLAG_g (1<<16)
-#define FLAG_z (1<<17)
-#define FLAG_f (1<<18)
-#define FLAG_i (1<<19)
+#define FLAG_4 (1LL<<0)
+#define FLAG_6 (1LL<<1)
+#define FLAG_F (1LL<<2)
+#define FLAG_U (1LL<<3)
+#define FLAG_I (1LL<<4)
+#define FLAG_l (1LL<<5)
+#define FLAG_d (1LL<<6)
+#define FLAG_n (1LL<<7)
+#define FLAG_v (1LL<<8)
+#define FLAG_r (1LL<<9)
+#define FLAG_m (1LL<<10)
+#define FLAG_p (1LL<<11)
+#define FLAG_q (1LL<<12)
+#define FLAG_s (1LL<<13)
+#define FLAG_t (1LL<<14)
+#define FLAG_w (1LL<<15)
+#define FLAG_g (1LL<<16)
+#define FLAG_z (1LL<<17)
+#define FLAG_f (1LL<<18)
+#define FLAG_i (1LL<<19)
 #endif
 
 #ifdef FOR_true
@@ -6779,8 +7013,8 @@
 #ifndef TT
 #define TT this.truncate
 #endif
-#define FLAG_c (1<<0)
-#define FLAG_s (1<<1)
+#define FLAG_c (1LL<<0)
+#define FLAG_s (1LL<<1)
 #endif
 
 #ifdef FOR_tty
@@ -6788,7 +7022,7 @@
 #ifndef TT
 #define TT this.tty
 #endif
-#define FLAG_s (1<<0)
+#define FLAG_s (1LL<<0)
 #endif
 
 #ifdef FOR_tunctl
@@ -6796,10 +7030,10 @@
 #ifndef TT
 #define TT this.tunctl
 #endif
-#define FLAG_T (1<<0)
-#define FLAG_u (1<<1)
-#define FLAG_d (1<<2)
-#define FLAG_t (1<<3)
+#define FLAG_T (1LL<<0)
+#define FLAG_u (1LL<<1)
+#define FLAG_d (1LL<<2)
+#define FLAG_t (1LL<<3)
 #endif
 
 #ifdef FOR_uclampset
@@ -6807,11 +7041,11 @@
 #ifndef TT
 #define TT this.uclampset
 #endif
-#define FLAG_R (1<<0)
-#define FLAG_M (1<<1)
-#define FLAG_m (1<<2)
-#define FLAG_a (1<<3)
-#define FLAG_p (1<<4)
+#define FLAG_R (1LL<<0)
+#define FLAG_M (1LL<<1)
+#define FLAG_m (1LL<<2)
+#define FLAG_a (1LL<<3)
+#define FLAG_p (1LL<<4)
 #endif
 
 #ifdef FOR_ulimit
@@ -6819,26 +7053,26 @@
 #ifndef TT
 #define TT this.ulimit
 #endif
-#define FLAG_c (1<<0)
-#define FLAG_d (1<<1)
-#define FLAG_e (1<<2)
-#define FLAG_f (1<<3)
-#define FLAG_i (1<<4)
-#define FLAG_l (1<<5)
-#define FLAG_m (1<<6)
-#define FLAG_n (1<<7)
-#define FLAG_p (1<<8)
-#define FLAG_q (1<<9)
-#define FLAG_R (1<<10)
-#define FLAG_r (1<<11)
-#define FLAG_s (1<<12)
-#define FLAG_t (1<<13)
-#define FLAG_u (1<<14)
-#define FLAG_v (1<<15)
-#define FLAG_a (1<<16)
-#define FLAG_H (1<<17)
-#define FLAG_S (1<<18)
-#define FLAG_P (1<<19)
+#define FLAG_c (1LL<<0)
+#define FLAG_d (1LL<<1)
+#define FLAG_e (1LL<<2)
+#define FLAG_f (1LL<<3)
+#define FLAG_i (1LL<<4)
+#define FLAG_l (1LL<<5)
+#define FLAG_m (1LL<<6)
+#define FLAG_n (1LL<<7)
+#define FLAG_p (1LL<<8)
+#define FLAG_q (1LL<<9)
+#define FLAG_R (1LL<<10)
+#define FLAG_r (1LL<<11)
+#define FLAG_s (1LL<<12)
+#define FLAG_t (1LL<<13)
+#define FLAG_u (1LL<<14)
+#define FLAG_v (1LL<<15)
+#define FLAG_a (1LL<<16)
+#define FLAG_H (1LL<<17)
+#define FLAG_S (1LL<<18)
+#define FLAG_P (1LL<<19)
 #endif
 
 #ifdef FOR_umount
@@ -6846,16 +7080,16 @@
 #ifndef TT
 #define TT this.umount
 #endif
-#define FLAG_v (1<<0)
-#define FLAG_t (1<<1)
-#define FLAG_a (1<<2)
-#define FLAG_r (1<<3)
-#define FLAG_l (1<<4)
-#define FLAG_f (1<<5)
-#define FLAG_D (1<<6)
-#define FLAG_d (1<<7)
-#define FLAG_n (1<<8)
-#define FLAG_c (1<<9)
+#define FLAG_v (1LL<<0)
+#define FLAG_t (1LL<<1)
+#define FLAG_a (1LL<<2)
+#define FLAG_r (1LL<<3)
+#define FLAG_l (1LL<<4)
+#define FLAG_f (1LL<<5)
+#define FLAG_D (1LL<<6)
+#define FLAG_d (1LL<<7)
+#define FLAG_n (1LL<<8)
+#define FLAG_c (1LL<<9)
 #endif
 
 #ifdef FOR_uname
@@ -6863,13 +7097,14 @@
 #ifndef TT
 #define TT this.uname
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_n (1<<1)
-#define FLAG_r (1<<2)
-#define FLAG_v (1<<3)
-#define FLAG_m (1<<4)
-#define FLAG_o (1<<5)
-#define FLAG_a (1<<6)
+#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_unicode
@@ -6884,14 +7119,14 @@
 #ifndef TT
 #define TT this.uniq
 #endif
-#define FLAG_u (1<<0)
-#define FLAG_d (1<<1)
-#define FLAG_c (1<<2)
-#define FLAG_i (1<<3)
-#define FLAG_z (1<<4)
-#define FLAG_w (1<<5)
-#define FLAG_s (1<<6)
-#define FLAG_f (1<<7)
+#define FLAG_u (1LL<<0)
+#define FLAG_d (1LL<<1)
+#define FLAG_c (1LL<<2)
+#define FLAG_i (1LL<<3)
+#define FLAG_z (1LL<<4)
+#define FLAG_w (1LL<<5)
+#define FLAG_s (1LL<<6)
+#define FLAG_f (1LL<<7)
 #endif
 
 #ifdef FOR_unix2dos
@@ -6923,14 +7158,16 @@
 #ifndef TT
 #define TT this.unshare
 #endif
-#define FLAG_U (1<<0)
-#define FLAG_u (1<<1)
-#define FLAG_p (1<<2)
-#define FLAG_n (1<<3)
-#define FLAG_m (1<<4)
-#define FLAG_i (1<<5)
-#define FLAG_r (1<<6)
-#define FLAG_f (1<<7)
+#define FLAG_U (1LL<<0)
+#define FLAG_u (1LL<<1)
+#define FLAG_p (1LL<<2)
+#define FLAG_n (1LL<<3)
+#define FLAG_m (1LL<<4)
+#define FLAG_i (1LL<<5)
+#define FLAG_C (1LL<<6)
+#define FLAG_r (1LL<<7)
+#define FLAG_f (1LL<<8)
+#define FLAG_a (1LL<<9)
 #endif
 
 #ifdef FOR_uptime
@@ -6938,8 +7175,8 @@
 #ifndef TT
 #define TT this.uptime
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_p (1<<1)
+#define FLAG_s (1LL<<0)
+#define FLAG_p (1LL<<1)
 #endif
 
 #ifdef FOR_useradd
@@ -6977,7 +7214,7 @@
 #ifndef TT
 #define TT this.uudecode
 #endif
-#define FLAG_o (1<<0)
+#define FLAG_o (1LL<<0)
 #endif
 
 #ifdef FOR_uuencode
@@ -6985,7 +7222,7 @@
 #ifndef TT
 #define TT this.uuencode
 #endif
-#define FLAG_m (1<<0)
+#define FLAG_m (1LL<<0)
 #endif
 
 #ifdef FOR_uuidgen
@@ -6993,7 +7230,7 @@
 #ifndef TT
 #define TT this.uuidgen
 #endif
-#define FLAG_r (1<<0)
+#define FLAG_r (1LL<<0)
 #endif
 
 #ifdef FOR_vconfig
@@ -7008,7 +7245,7 @@
 #ifndef TT
 #define TT this.vi
 #endif
-#define FLAG_s (1<<0)
+#define FLAG_s (1LL<<0)
 #endif
 
 #ifdef FOR_vmstat
@@ -7016,7 +7253,7 @@
 #ifndef TT
 #define TT this.vmstat
 #endif
-#define FLAG_n (1<<0)
+#define FLAG_n (1LL<<0)
 #endif
 
 #ifdef FOR_w
@@ -7039,11 +7276,11 @@
 #ifndef TT
 #define TT this.watch
 #endif
-#define FLAG_x (1<<0)
-#define FLAG_b (1<<1)
-#define FLAG_e (1<<2)
-#define FLAG_t (1<<3)
-#define FLAG_n (1<<4)
+#define FLAG_x (1LL<<0)
+#define FLAG_b (1LL<<1)
+#define FLAG_e (1LL<<2)
+#define FLAG_t (1LL<<3)
+#define FLAG_n (1LL<<4)
 #endif
 
 #ifdef FOR_watchdog
@@ -7061,10 +7298,10 @@
 #ifndef TT
 #define TT this.wc
 #endif
-#define FLAG_l (1<<0)
-#define FLAG_w (1<<1)
-#define FLAG_c (1<<2)
-#define FLAG_m (1<<3)
+#define FLAG_l (1LL<<0)
+#define FLAG_w (1LL<<1)
+#define FLAG_c (1LL<<2)
+#define FLAG_m (1LL<<3)
 #endif
 
 #ifdef FOR_wget
@@ -7083,7 +7320,7 @@
 #ifndef TT
 #define TT this.which
 #endif
-#define FLAG_a (1<<0)
+#define FLAG_a (1LL<<0)
 #endif
 
 #ifdef FOR_who
@@ -7099,15 +7336,15 @@
 #ifndef TT
 #define TT this.xargs
 #endif
-#define FLAG_0 (1<<0)
-#define FLAG_s (1<<1)
-#define FLAG_n (1<<2)
-#define FLAG_r (1<<3)
-#define FLAG_t (1<<4)
-#define FLAG_p (1<<5)
-#define FLAG_o (1<<6)
-#define FLAG_P (1<<7)
-#define FLAG_E (1<<8)
+#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
 
 #ifdef FOR_xxd
@@ -7115,14 +7352,15 @@
 #ifndef TT
 #define TT this.xxd
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_r (1<<1)
-#define FLAG_p (1<<2)
-#define FLAG_i (1<<3)
-#define FLAG_g (1<<4)
-#define FLAG_o (1<<5)
-#define FLAG_l (1<<6)
-#define FLAG_c (1<<7)
+#define FLAG_s (1LL<<0)
+#define FLAG_r (1LL<<1)
+#define FLAG_p (1LL<<2)
+#define FLAG_i (1LL<<3)
+#define FLAG_e (1LL<<4)
+#define FLAG_g (1LL<<5)
+#define FLAG_o (1LL<<6)
+#define FLAG_l (1LL<<7)
+#define FLAG_c (1LL<<8)
 #endif
 
 #ifdef FOR_xzcat
@@ -7144,18 +7382,19 @@
 #ifndef TT
 #define TT this.zcat
 #endif
-#define FLAG_9 (1<<0)
-#define FLAG_8 (1<<1)
-#define FLAG_7 (1<<2)
-#define FLAG_6 (1<<3)
-#define FLAG_5 (1<<4)
-#define FLAG_4 (1<<5)
-#define FLAG_3 (1<<6)
-#define FLAG_2 (1<<7)
-#define FLAG_1 (1<<8)
-#define FLAG_k (1<<9)
-#define FLAG_f (1<<10)
-#define FLAG_d (1<<11)
-#define FLAG_c (1<<12)
+#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)
 #endif
 
diff --git a/android/device/generated/globals.h b/android/device/generated/globals.h
index 403077b..2b646d0 100644
--- a/android/device/generated/globals.h
+++ b/android/device/generated/globals.h
@@ -2,6 +2,8 @@
 
 struct log_data {
   char *t, *p;
+
+  int pri;
 };
 
 // toys/example/demo_number.c
@@ -25,7 +27,7 @@
       long c;
       struct arg_list *d;
       long e;
-      char *also, *blubber;
+      char *f, *g, *h, *also, *blubber;
     } s;
     struct {
       long b;
@@ -99,9 +101,8 @@
 // toys/lsb/mount.c
 
 struct mount_data {
-  struct arg_list *optlist;
-  char *type;
-  char *bigO;
+  struct arg_list *o;
+  char *t, *O;
 
   unsigned long flags;
   char *opts;
@@ -213,6 +214,22 @@
   char *u;
 };
 
+// toys/net/wget.c
+
+struct wget_data {
+  char *p, *O;
+  long max_redirect;
+
+  int sock, https;
+  char *url;
+#if CFG_WGET_LIBTLS
+  struct tls *tls;
+#elif CFG_TOYBOX_LIBCRYPTO
+  struct ssl_ctx_st *ctx;
+  struct ssl_st *ssl;
+#endif
+};
+
 // toys/other/acpi.c
 
 struct acpi_data {
@@ -224,6 +241,7 @@
 
 struct base64_data {
   long w;
+
   unsigned total;
   unsigned n;  // number of bits used in encoding. 5 for base32, 6 for base64
   unsigned align;  // number of bits to align to
@@ -239,6 +257,7 @@
 
 struct blkid_data {
   struct arg_list *s;
+  char *o;
 };
 
 // toys/other/blockdev.c
@@ -268,7 +287,7 @@
 // toys/other/fmt.c
 
 struct fmt_data {
-  int width;
+  long width;
 
   int level, pos;
 };
@@ -343,7 +362,7 @@
 
 struct lsusb_data {
   char *i;
-  long n;
+  long x, n;
 
   void *ids, *class;
   int count;
@@ -384,10 +403,18 @@
   int count;
 };
 
+// toys/other/nbd_client.c
+
+struct nbd_client_data {
+  long b;
+
+  int nbd;
+};
+
 // toys/other/nsenter.c
 
 struct nsenter_data {
-  char *Uupnmi[6];
+  char *UupnmiC[6];
   long t;
 };
 
@@ -419,6 +446,12 @@
   int bits, endian, shnum, shentsize, phentsize;
 };
 
+// toys/other/readlink.c
+
+struct readlink_data {
+  char *R, *relative_base;
+};
+
 // toys/other/reboot.c
 
 struct reboot_data {
@@ -451,6 +484,15 @@
   long o, n, s;
 };
 
+// toys/other/shuf.c
+
+struct shuf_data {
+  long n;
+
+  char **lines;
+  long count;
+};
+
 // toys/other/stat.c
 
 struct stat_data {
@@ -489,11 +531,9 @@
 struct timeout_data {
   char *s, *k;
 
-  int nextsig;
-  pid_t pid;
-  struct timespec kts;
-  struct itimerspec its;
-  timer_t timer;
+  struct pollfd pfd;
+  sigjmp_buf sj;
+  int fds[2], pid;
 };
 
 // toys/other/truncate.c
@@ -616,8 +656,7 @@
 
 struct dd_data {
   int show_xfer, show_records;
-  unsigned long long bytes, c_count, in_full, in_part, out_full, out_part;
-  struct timeval start;
+  unsigned long long bytes, in_full, in_part, out_full, out_part, start;
   struct {
     char *name;
     int fd;
@@ -667,13 +706,20 @@
 // toys/pending/diff.c
 
 struct diff_data {
-  long ct;
-  char *start;
-  struct arg_list *L_list;
+  long U;
+  struct arg_list *L;
+  char *F, *S, *new_line_format, *old_line_format, *unchanged_line_format;
 
-  int dir_num, size, is_binary, status, change, len[2];
-  int *offset[2];
+  int dir_num, size, is_binary, differ, change, len[2], *offset[2];
   struct stat st[2];
+  struct {
+    char **list;
+    int nr_elm;
+  } dir[2];
+  struct {
+    FILE *fp;
+    int len;
+  } file[2];
 };
 
 // toys/pending/dumpleases.c
@@ -745,6 +791,13 @@
   struct termios termios;
 };
 
+// toys/pending/git.c
+
+struct git_data {
+  char *url, *name; //git repo remote url and init directory name
+  struct IndexV2 *i; //git creates a index for each pack file, git clone just needs one index for the received pack file
+};
+
 // toys/pending/groupadd.c
 
 struct groupadd_data {
@@ -890,7 +943,7 @@
   long long SECONDS;
   char *isexec, *wcpat;
   unsigned options, jobcnt, LINENO;
-  int hfd, pid, bangpid, varslen, srclvl, recursion;
+  int hfd, pid, bangpid, srclvl, recursion;
 
   // Callable function array
   struct sh_function {
@@ -916,11 +969,11 @@
       long flags;
       char *str;
     } *vars;
-    long varslen, shift;
+    long varslen, varscap, shift, oldlineno;
 
     struct sh_function *func; // TODO wire this up
     struct sh_pipeline *pl;
-    char *ifs;
+    char *ifs, *omnom;
     struct sh_arg arg;
     struct arg_list *delete;
 
@@ -998,11 +1051,8 @@
 // toys/pending/tcpsvd.c
 
 struct tcpsvd_data {
-  char *name;
-  char *user;
-  long bn;
-  char *nmsg;
-  long cn;
+  char *l, *u, *C;
+  long b, c;
 
   int maxc;
   int count_all;
@@ -1100,6 +1150,8 @@
 
 struct vi_data {
   char *s;
+
+  char *filename;
   int vi_mode, tabstop, list;
   int cur_col, cur_row, scr_row;
   int drawn_row, drawn_col;
@@ -1119,13 +1171,9 @@
     char* data;
   } yank;
 
-  int modified;
   size_t filesize;
 // mem_block contains RO data that is either original file as mmap
 // or heap allocated inserted data
-//
-//
-//
   struct block_list {
     struct block_list *next, *prev;
     struct mem_block {
@@ -1156,22 +1204,6 @@
   } *slices;
 };
 
-// toys/pending/wget.c
-
-struct wget_data {
-  char *p, *O;
-  long max_redirect;
-
-  int sock, https;
-  char *url;
-#if CFG_WGET_LIBTLS
-  struct tls *tls;
-#elif CFG_WGET_OPENSSL
-  struct ssl_ctx_st *ctx;
-  struct ssl_st *ssl;
-#endif
-};
-
 // toys/posix/basename.c
 
 struct basename_data {
@@ -1239,7 +1271,7 @@
 // toys/posix/cpio.c
 
 struct cpio_data {
-  char *F, *H;
+  char *F, *H, *R;
 };
 
 // toys/posix/cut.c
@@ -1320,8 +1352,8 @@
 
   char *purple, *cyan, *red, *green, *grey;
   struct double_list *reg;
-  char indelim, outdelim;
-  int found, tried;
+  int found, tried, delim;
+  struct arg_list *fixed[256];
 };
 
 // toys/posix/head.c
@@ -1363,14 +1395,15 @@
 
 struct logger_data {
   char *p, *t;
+
+  int priority;
 };
 
 // toys/posix/ls.c
 
 struct ls_data {
-  long w;
-  long l;
-  char *color;
+  long w, l;
+  char *color, *sort;
 
   struct dirtree *files, *singledir;
   unsigned screen_width;
@@ -1465,7 +1498,10 @@
     } pgrep;
   };
 
-  struct ptr_len gg, GG, pp, PP, ss, tt, uu, UU;
+  struct ps_ptr_len {
+    void *ptr;
+    long len;
+  } gg, GG, pp, PP, ss, tt, uu, UU;
   struct dirtree *threadparent;
   unsigned width, height, scroll;
   dev_t tty;
@@ -1491,12 +1527,12 @@
   // processed pattern list
   struct double_list *pattern;
 
-  char *nextline, *remember;
+  char *nextline, *remember, *tarxform;
   void *restart, *lastregex;
   long nextlen, rememberlen, count;
   int fdout, noeol;
-  unsigned xx;
-  char delim;
+  unsigned xx, tarxlen, xflags;
+  char delim, xftype;
 };
 
 // toys/posix/sort.c
@@ -1537,32 +1573,31 @@
   struct {
     char *path;
     int fd;
-    dev_t dev;
-    ino_t ino;
+    struct dev_ino di;
   } *F;
 };
 
 // toys/posix/tar.c
 
 struct tar_data {
-  char *f, *C;
-  struct arg_list *T, *X;
-  char *I, *to_command, *owner, *group, *mtime, *mode;
+  char *f, *C, *I;
+  struct arg_list *T, *X, *xform;
+  long strip;
+  char *to_command, *owner, *group, *mtime, *mode, *sort;
   struct arg_list *exclude;
-  long strip_components;
 
   struct double_list *incl, *excl, *seen;
   struct string_list *dirs;
-  char *cwd;
-  int fd, ouid, ggid, hlc, warn, adev, aino, sparselen, pid;
+  char *cwd, **xfsed;
+  int fd, ouid, ggid, hlc, warn, sparselen, pid, xfpipe[2];
+  struct dev_ino archive_di;
   long long *sparse;
   time_t mtt;
 
   // hardlinks seen so far (hlc many)
   struct {
     char *arg;
-    ino_t ino;
-    dev_t dev;
+    struct dev_ino di;
   } *hlx;
 
   // Parsed information about a tar header.
@@ -1654,6 +1689,7 @@
 	struct ping_data ping;
 	struct sntp_data sntp;
 	struct tunctl_data tunctl;
+	struct wget_data wget;
 	struct acpi_data acpi;
 	struct base64_data base64;
 	struct blkdiscard_data blkdiscard;
@@ -1677,16 +1713,19 @@
 	struct mkpasswd_data mkpasswd;
 	struct mkswap_data mkswap;
 	struct modinfo_data modinfo;
+	struct nbd_client_data nbd_client;
 	struct nsenter_data nsenter;
 	struct oneit_data oneit;
 	struct openvt_data openvt;
 	struct pwgen_data pwgen;
 	struct readelf_data readelf;
+	struct readlink_data readlink;
 	struct reboot_data reboot;
 	struct rtcwake_data rtcwake;
 	struct setfattr_data setfattr;
 	struct sha3sum_data sha3sum;
 	struct shred_data shred;
+	struct shuf_data shuf;
 	struct stat_data stat;
 	struct swapon_data swapon;
 	struct switch_root_data switch_root;
@@ -1718,6 +1757,7 @@
 	struct getfattr_data getfattr;
 	struct getopt_data getopt;
 	struct getty_data getty;
+	struct git_data git;
 	struct groupadd_data groupadd;
 	struct hexdump_data hexdump;
 	struct ip_data ip;
@@ -1745,7 +1785,6 @@
 	struct traceroute_data traceroute;
 	struct useradd_data useradd;
 	struct vi_data vi;
-	struct wget_data wget;
 	struct basename_data basename;
 	struct cal_data cal;
 	struct chgrp_data chgrp;
diff --git a/android/device/generated/help.h b/android/device/generated/help.h
index 04e6212..72a74f5 100644
--- a/android/device/generated/help.h
+++ b/android/device/generated/help.h
@@ -80,9 +80,7 @@
 
 #define HELP_mktemp "usage: mktemp [-dqu] [-p DIR] [TEMPLATE]\n\nSafely create a new file \"DIR/TEMPLATE\" and print its name.\n\n-d	Create directory instead of file (--directory)\n-p	Put new file in DIR (--tmpdir)\n-q	Quiet, no error messages\n-t	Prefer $TMPDIR > DIR > /tmp (default DIR > $TMPDIR > /tmp)\n-u	Don't create anything, just print what would be created\n\nEach X in TEMPLATE is replaced with a random printable character. The\ndefault TEMPLATE is tmp.XXXXXXXXXX."
 
-#define HELP_mknod_z "usage: mknod [-Z CONTEXT] ...\n\n-Z	Set security context to created file"
-
-#define HELP_mknod "usage: mknod [-m MODE] NAME TYPE [MAJOR MINOR]\n\nCreate a special file NAME with a given type. TYPE is b for block device,\nc or u for character device, p for named pipe (which ignores MAJOR/MINOR).\n\n-m	Mode (file permissions) of new device, in octal or u+x format"
+#define HELP_mknod "usage: mknod [-Z CONTEXT] ... [-m MODE] NAME TYPE [MAJOR MINOR]\n\nCreate a special file NAME with a given type. TYPE is b for block device,\nc or u for character device, p for named pipe (which ignores MAJOR/MINOR).\n-Z	Set security context to created file\n-m	Mode (file permissions) of new device, in octal or u+x format"
 
 #define HELP_sha512sum "See md5sum"
 
@@ -104,15 +102,19 @@
 
 #define HELP_zcat "usage: zcat [FILE...]\n\nDecompress files to stdout. Like `gzip -dc`.\n\n-f	Force: allow read from tty"
 
-#define HELP_gunzip "usage: gunzip [-cfk] [FILE...]\n\nDecompress files. With no files, decompresses stdin to stdout.\nOn success, the input files are removed and replaced by new\nfiles without the .gz suffix.\n\n-c	Output to stdout (act as zcat)\n-f	Force: allow read from tty\n-k	Keep input files (default is to remove)"
+#define HELP_gunzip "usage: gunzip [-cfkt] [FILE...]\n\nDecompress files. With no files, decompresses stdin to stdout.\nOn success, the input files are removed and replaced by new\nfiles without the .gz suffix.\n\n-c	Output to stdout (act as zcat)\n-f	Force: allow read from tty\n-k	Keep input files (default is to remove)\n-t	Test integrity"
 
-#define HELP_gzip "usage: gzip [-19cdfk] [FILE...]\n\nCompress files. With no files, compresses stdin to stdout.\nOn success, the input files are removed and replaced by new\nfiles with the .gz suffix.\n\n-c	Output to stdout\n-d	Decompress (act as gunzip)\n-f	Force: allow overwrite of output file\n-k	Keep input files (default is to remove)\n-#	Compression level 1-9 (1:fastest, 6:default, 9:best)"
+#define HELP_gzip "usage: gzip [-19cdfkt] [FILE...]\n\nCompress files. With no files, compresses stdin to stdout.\nOn success, the input files are removed and replaced by new\nfiles with the .gz suffix.\n\n-c	Output to stdout\n-d	Decompress (act as gunzip)\n-f	Force: allow overwrite of output file\n-k	Keep input files (default is to remove)\n-t	Test integrity\n-#	Compression level 1-9 (1:fastest, 6:default, 9:best)"
 
 #define HELP_dmesg "usage: dmesg [-Cc] [-r|-t|-T] [-n LEVEL] [-s SIZE] [-w]\n\nPrint or control the kernel ring buffer.\n\n-C	Clear ring buffer without printing\n-c	Clear ring buffer after printing\n-n	Set kernel logging LEVEL (1-9)\n-r	Raw output (with <level markers>)\n-S	Use syslog(2) rather than /dev/kmsg\n-s	Show the last SIZE many bytes\n-T	Human readable timestamps\n-t	Don't print timestamps\n-w	Keep waiting for more output (aka --follow)"
 
+#define HELP_wget_libtls "Enable HTTPS support for wget by linking to LibTLS.\nSupports using libtls, libretls or libtls-bearssl.\n\nUse TOYBOX_LIBCRYPTO to enable HTTPS support via OpenSSL."
+
+#define HELP_wget "usage: wget [OPTIONS]... [URL]\n    --max-redirect          maximum redirections allowed\n-d, --debug                 print lots of debugging information\n-O, --output-document=FILE  specify output filename\n-p, --post-data=DATA        send data in body of POST request\n\nexamples:\n  wget http://www.example.com"
+
 #define HELP_tunctl "usage: tunctl [-dtT] [-u USER] NAME\n\nCreate and delete tun/tap virtual ethernet devices.\n\n-T	Use tap (ethernet frames) instead of tun (ip packets)\n-d	Delete tun/tap device\n-t	Create tun/tap device\n-u	Set owner (user who can read/write device without root access)"
 
-#define HELP_sntp "usage: sntp [-saSdDq] [-r SHIFT] [-mM[ADDRESS]] [-p PORT] [SERVER]\n\nSimple Network Time Protocol client. Query SERVER and display time.\n\n-p	Use PORT (default 123)\n-s	Set system clock suddenly\n-a	Adjust system clock gradually\n-S	Serve time instead of querying (bind to SERVER address if specified)\n-m	Wait for updates from multicast ADDRESS (RFC 4330 default 224.0.1.1)\n-M	Multicast server on ADDRESS (default 224.0.0.1)\n-t	TTL (multicast only, default 1)\n-d	Daemonize (run in background re-querying )\n-D	Daemonize but stay in foreground: re-query time every 1000 seconds\n-r	Retry shift (every 1<<SHIFT seconds)\n-q	Quiet (don't display time)"
+#define HELP_sntp "usage: sntp [-saSdDq] [-r SHIFT] [-mM[ADDRESS]] [-p PORT] [SERVER]\n\nSimple Network Time Protocol client. Query SERVER and display time.\n\n-p	Use PORT (default 123)\n-s	Set system clock suddenly\n-a	Adjust system clock gradually\n-S	Serve time instead of querying (bind to SERVER address if specified)\n-m	Wait for updates from multicast ADDRESS (RFC 4330 suggests 224.0.1.1)\n-M	Multicast server on ADDRESS (RFC 4330 suggests 224.0.1.1)\n-t	TTL (multicast only, default 1)\n-d	Daemonize (run in background re-querying)\n-D	Daemonize but stay in foreground: re-query time every 1000 seconds\n-r	Retry shift (every 1<<SHIFT seconds)\n-q	Quiet (don't display time)"
 
 #define HELP_rfkill "usage: rfkill COMMAND [DEVICE]\n\nEnable/disable wireless devices.\n\nCommands:\nlist [DEVICE]   List current state\nblock DEVICE    Disable device\nunblock DEVICE  Enable device\n\nDEVICE is an index number, or one of:\nall, wlan(wifi), bluetooth, uwb(ultrawideband), wimax, wwan, gps, fm."
 
@@ -120,12 +122,14 @@
 
 #define HELP_netstat "usage: netstat [-pWrxwutneal]\n\nDisplay networking information. Default is netstat -tuwx\n\n-r	Routing table\n-a	All sockets (not just connected)\n-l	Listening server sockets\n-t	TCP sockets\n-u	UDP sockets\n-w	Raw sockets\n-x	Unix sockets\n-e	Extended info\n-n	Don't resolve names\n-W	Wide display\n-p	Show PID/program name of sockets"
 
-#define HELP_netcat "usage: netcat [-46ELUlt] [-u] [-wpq #] [-s addr] {IPADDR PORTNUM|-f FILENAME|COMMAND...}\n\nForward stdin/stdout to a file or network connection.\n\n-4	Force IPv4\n-6	Force IPv6\n-E	Forward stderr\n-L	Listen and background each incoming connection (server mode)\n-U	Use a UNIX domain socket\n-W	SECONDS timeout for more data on an idle connection\n-f	Use FILENAME (ala /dev/ttyS0) instead of network\n-l	Listen for one incoming connection, then exit\n-p	Local port number\n-q	Quit SECONDS after EOF on stdin, even if stdout hasn't closed yet\n-s	Local source address\n-t	Allocate tty\n-u	Use UDP\n-w	SECONDS timeout to establish connection\n\nUse \"stty 115200 -F /dev/ttyS0 && stty raw -echo -ctlecho\" with\nnetcat -f to connect to a serial port.\n\nWhen listening the COMMAND line is executed as a child process to handle\nan incoming connection. With no COMMAND -l forwards the connection\nto stdin/stdout. If no -p specified, -l prints the port it bound to and\nbackgrounds itself (returning immediately).\n\nFor a quick-and-dirty server, try something like:\nnetcat -s 127.0.0.1 -p 1234 -tL sh -l"
+#define HELP_netcat "usage: netcat [-46ElLtUu] [-wpq #] [-s addr] {IPADDR PORTNUM|-f FILENAME|COMMAND...}\n\nForward stdin/stdout to a file or network connection.\n\n-4	Force IPv4\n-6	Force IPv6\n-E	Forward stderr\n-f	Use FILENAME (ala /dev/ttyS0) instead of network\n-l	Listen for one incoming connection, then exit\n-L	Listen and background each incoming connection (server mode)\n-n	No DNS lookup\n-p	Local port number\n-q	Quit SECONDS after EOF on stdin, even if stdout hasn't closed yet\n-s	Local source address\n-t	Allocate tty\n-u	Use UDP\n-U	Use a UNIX domain socket\n-w	SECONDS timeout to establish connection\n-W	SECONDS timeout for more data on an idle connection\n\nWhen listening the COMMAND line is executed as a child process to handle\nan incoming connection. With no COMMAND -l forwards the connection\nto stdin/stdout. If no -p specified, -l prints the port it bound to and\nbackgrounds itself (returning immediately).\n\nFor a quick-and-dirty server, try something like:\nnetcat -s 127.0.0.1 -p 1234 -tL sh -l\n\nOr use \"stty 115200 -F /dev/ttyS0 && stty raw -echo -ctlecho\" with\nnetcat -f to connect to a serial port."
 
 #define HELP_microcom "usage: microcom [-s SPEED] [-X] DEVICE\n\nSimple serial console.\n\n-s	Set baud rate to SPEED (default 115200)\n-X	Ignore ^@ (send break) and ^] (exit)"
 
 #define HELP_ifconfig "usage: ifconfig [-aS] [INTERFACE [ACTION...]]\n\nDisplay or configure network interface.\n\nWith no arguments, display active interfaces. First argument is interface\nto operate on, one argument by itself displays that interface.\n\n-a	All interfaces displayed, not just active ones\n-S	Short view, one line per interface\n\nStandard ACTIONs to perform on an INTERFACE:\n\nADDR[/MASK]        - set IPv4 address (1.2.3.4/5) and activate interface\nadd|del ADDR[/LEN] - add/remove IPv6 address (1111::8888/128)\nup|down            - activate or deactivate interface\n\nAdvanced ACTIONs (default values usually suffice):\n\ndefault          - remove IPv4 address\nnetmask ADDR     - set IPv4 netmask via 255.255.255.0 instead of /24\ntxqueuelen LEN   - number of buffered packets before output blocks\nmtu LEN          - size of outgoing packets (Maximum Transmission Unit)\nbroadcast ADDR   - Set broadcast address\npointopoint ADDR - PPP and PPPOE use this instead of \"route add default gw\"\nhw TYPE ADDR     - set hardware (mac) address (type = ether|infiniband)\nrename NEWNAME   - rename interface\n\nFlags you can set on an interface (or -remove by prefixing with -):\n\narp       - don't use Address Resolution Protocol to map LAN routes\npromisc   - don't discard packets that aren't to this LAN hardware address\nmulticast - force interface into multicast mode if the driver doesn't\nallmulti  - promisc for multicast packets"
 
+#define HELP_httpd "usage: httpd [-e STR] [DIR]\n\nServe contents of directory as static web pages.\n\n-e	Escape STR as URL, printing result and exiting.\n-d	Decode escaped STR, printing result and exiting.\n-v	Verbose"
+
 #define HELP_host "usage: host [-v] [-t TYPE] NAME [SERVER]\n\nLook up DNS records for NAME, either domain name or IPv4/IPv6 address to\nreverse lookup, from SERVER or default DNS server(s).\n\n-a	All records\n-t TYPE	Record TYPE (number or ANY A AAAA CNAME MX NS PTR SOA SRV TXT)\n-v	Verbose"
 
 #define HELP_ftpput "An ftpget that defaults to -s instead of -g"
@@ -134,7 +138,7 @@
 
 #define HELP_yes "usage: yes [args...]\n\nRepeatedly output line until killed. If no args, output 'y'."
 
-#define HELP_xxd "usage: xxd [-c n] [-g n] [-i] [-l n] [-o n] [-p] [-r] [-s n] [file]\n\nHexdump a file to stdout. If no file is listed, copy from stdin.\nFilename \"-\" is a synonym for stdin.\n\n-c n	Show n bytes per line (default 16)\n-g n	Group bytes by adding a ' ' every n bytes (default 2)\n-i	Output include file (CSV hex bytes, plus C header/footer if not stdin)\n-l n	Limit of n bytes before stopping (default is no limit)\n-o n	Add n to display offset\n-p	Plain hexdump (30 bytes/line, no grouping)\n-r	Reverse operation: turn a hexdump into a binary file\n-s n	Skip to offset n"
+#define HELP_xxd "usage: xxd [-eipr] [-cglos N] [file]\n\nHexdump a file to stdout. If no file is listed, copy from stdin.\nFilename \"-\" is a synonym for stdin.\n\n-c N	Show N bytes per line (default 16)\n-e	Little-endian\n-g N	Group bytes by adding a ' ' every N bytes (default 2)\n-i	Output include file (CSV hex bytes, plus C header/footer if not stdin)\n-l N	Limit of N bytes before stopping (default is no limit)\n-o N	Add N to display offset\n-p	Plain hexdump (30 bytes/line, no grouping. With -c 0 no wrap/group)\n-r	Reverse operation: turn a hexdump into a binary file\n-s N	Skip to offset N"
 
 #define HELP_which "usage: which [-a] filename ...\n\nSearch $PATH for executable files matching filename(s).\n\n-a	Show all matches"
 
@@ -158,7 +162,7 @@
 
 #define HELP_truncate "usage: truncate [-c] -s SIZE file...\n\nSet length of file(s), extending sparsely if necessary.\n\n-c	Don't create file if it doesn't exist\n-s	New size (with optional prefix and suffix)\n\nSIZE prefix: + add, - subtract, < shrink to, > expand to,\n             / multiple rounding down, % multiple rounding up\nSIZE suffix: k=1024, m=1024^2, g=1024^3, t=1024^4, p=1024^5, e=1024^6"
 
-#define HELP_timeout "usage: timeout [-k DURATION] [-s SIGNAL] DURATION COMMAND...\n\nRun command line as a child process, sending child a signal if the\ncommand doesn't exit soon enough.\n\nDURATION can be a decimal fraction. An optional suffix can be \"m\"\n(minutes), \"h\" (hours), \"d\" (days), or \"s\" (seconds, the default).\n\n-s	Send specified signal (default TERM)\n-k	Send KILL signal if child still running this long after first signal\n-v	Verbose\n--foreground       Don't create new process group\n--preserve-status  Exit with the child's exit status"
+#define HELP_timeout "usage: timeout [-i] [-k DURATION] [-s SIGNAL] DURATION COMMAND...\n\nRun command line as a child process, sending child a signal if the\ncommand doesn't exit soon enough.\n\nDURATION can be a decimal fraction. An optional suffix can be \"m\"\n(minutes), \"h\" (hours), \"d\" (days), or \"s\" (seconds, the default).\n\n-i	Only kill for inactivity (restart timeout when command produces output)\n-k	Send KILL signal if child still running this long after first signal\n-s	Send specified signal (default TERM)\n-v	Verbose\n--foreground       Don't create new process group\n--preserve-status  Exit with the child's exit status"
 
 #define HELP_taskset "usage: taskset [-ap] [mask] [PID | cmd [args...]]\n\nLaunch a new task which may only run on certain processors, or change\nthe processor affinity of an existing PID.\n\nMask is a hex string where each bit represents a processor the process\nis allowed to run on. PID without a mask displays existing affinity.\n\n-p	Set/get the affinity of given PID instead of a new command\n-a	Set/get the affinity of all threads of the PID"
 
@@ -172,10 +176,12 @@
 
 #define HELP_swapon "usage: swapon [-d] [-p priority] filename\n\nEnable swapping on a given device/file.\n\n-d	Discard freed SSD pages\n-p	Priority (highest priority areas allocated first)"
 
-#define HELP_swapoff "usage: swapoff swapregion\n\nDisable swapping on a given swapregion."
+#define HELP_swapoff "usage: swapoff FILE\n\nDisable swapping on a device or file."
 
 #define HELP_stat "usage: stat [-tfL] [-c FORMAT] FILE...\n\nDisplay status of files or filesystems.\n\n-c	Output specified FORMAT string instead of default\n-f	Display filesystem status instead of file status\n-L	Follow symlinks\n-t	terse (-c \"%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o\")\n	      (with -f = -c \"%n %i %l %t %s %S %b %f %a %c %d\")\n\nThe valid format escape sequences for files:\n%a  Access bits (octal) |%A  Access bits (flags)|%b  Size/512\n%B  Bytes per %b (512)  |%C  Security context   |%d  Device ID (dec)\n%D  Device ID (hex)     |%f  All mode bits (hex)|%F  File type\n%g  Group ID            |%G  Group name         |%h  Hard links\n%i  Inode               |%m  Mount point        |%n  Filename\n%N  Long filename       |%o  I/O block size     |%s  Size (bytes)\n%t  Devtype major (hex) |%T  Devtype minor (hex)|%u  User ID\n%U  User name           |%x  Access time        |%X  Access unix time\n%y  Modification time   |%Y  Mod unix time      |%z  Creation time\n%Z  Creation unix time\n\nThe valid format escape sequences for filesystems:\n%a  Available blocks    |%b  Total blocks       |%c  Total inodes\n%d  Free inodes         |%f  Free blocks        |%i  File system ID\n%l  Max filename length |%n  File name          |%s  Best transfer size\n%S  Actual block size   |%t  FS type (hex)      |%T  FS type (driver name)"
 
+#define HELP_shuf "usage: shuf [-ze] [-n COUNT] [FILE...]\n\nWrite lines of input to output in random order.\n\n-z	Input/output lines are NUL terminated.\n-n	Stop after COUNT many output lines.\n-e	Echo mode: arguments are inputs to shuffle, not files to read."
+
 #define HELP_shred "usage: shred [-fuxz] [-n COUNT] [-o OFFSET] [-s SIZE] FILE...\n\nSecurely delete a file by overwriting its contents with random data.\n\n-f		Force (chmod if necessary)\n-n COUNT	Random overwrite iterations (default 1)\n-o OFFSET	Start at OFFSET\n-s SIZE		Use SIZE instead of detecting file size\n-u		Unlink (actually delete file when done)\n-x		Use exact size (default without -s rounds up to next 4k)\n-z		Zero at end\n\nNote: data journaling filesystems render this command useless, you must\noverwrite all free space (fill up disk) to erase old data on those."
 
 #define HELP_sha3sum "usage: sha3sum [-S] [-a BITS] [FILE...]\n\nHash function du jour.\n\n-a	Produce a hash BITS long (default 224)\n-b	Brief (hash only, no filename)\n-S	Use SHAKE termination byte instead of SHA3 (ask FIPS why)"
@@ -194,9 +200,9 @@
 
 #define HELP_reboot "usage: reboot/halt/poweroff [-fn] [-d DELAY]\n\nRestart, halt, or power off the system.\n\n-d	Wait DELAY before proceeding (in seconds or m/h/d suffix: -d 1.5m = 90s)\n-f	Force reboot (don't signal init, reboot directly)\n-n	Don't sync filesystems before reboot"
 
-#define HELP_realpath "usage: realpath FILE...\n\nDisplay the canonical absolute pathname"
+#define HELP_realpath "usage: realpath [-LPemqsz] [--relative-base DIR] [-R DIR] FILE...\n\nDisplay the canonical absolute pathname\n\n-R Show ../path relative to DIR (--relative-to)\n-L Logical path (resolve .. before symlinks)\n-P Physical path (default)\n-e Canonical path to existing entry (fail if missing)\n-m Ignore missing entries, show where it would be\n-q Quiet (no error messages)\n-s Don't expand symlinks\n-z NUL instead of newline\n--relative-base  If path under DIR trim off prefix"
 
-#define HELP_readlink "usage: readlink FILE...\n\nWith no options, show what symlink points to, return error if not symlink.\n\nOptions for producing canonical paths (all symlinks/./.. resolved):\n\n-e	Canonical path to existing entry (fail if missing)\n-f	Full path (fail if directory missing)\n-m	Ignore missing entries, show where it would be\n-n	No trailing newline\n-q	Quiet (no output, just error code)"
+#define HELP_readlink "usage: readlink FILE...\n\nWith no options, show what symlink points to, return error if not symlink.\n\nOptions for producing canonical paths (all symlinks/./.. resolved):\n\n-e	Canonical path to existing entry (fail if missing)\n-f	Full path (fail if directory missing)\n-m	Ignore missing entries, show where it would be\n-n	No trailing newline\n-q	Quiet (no error messages)\n-z	NUL instead of newline"
 
 #define HELP_readelf "usage: readelf [-adehlnSs] [-p SECTION] [-x SECTION] [file...]\n\nDisplays information about ELF files.\n\n-a	Equivalent to -dhlnSs\n-d	Show dynamic section\n-e	Headers (equivalent to -hlS)\n-h	Show ELF header\n-l	Show program headers\n-n	Show notes\n-p S	Dump strings found in named/numbered section\n-S	Show section headers\n-s	Show symbol tables (.dynsym and .symtab)\n-x S	Hex dump of named/numbered section\n\n--dyn-syms	Show just .dynsym symbol table"
 
@@ -208,7 +214,7 @@
 
 #define HELP_printenv "usage: printenv [-0] [env_var...]\n\nPrint environment variables.\n\n-0	Use \\0 as delimiter instead of \\n"
 
-#define HELP_pmap "usage: pmap [-pqx] PID...\n\nReport the memory map of a process or processes.\n\n-q	Show full paths\n-q	Do not show header or footer\n-x	Show the extended format"
+#define HELP_pmap "usage: pmap [-pqx] PID...\n\nReport the memory map of a process or processes.\n\n-p	Show full paths\n-q	Do not show header or footer\n-x	Show the extended format"
 
 #define HELP_pivot_root "usage: pivot_root OLD NEW\n\nSwap OLD and NEW filesystems (as if by simultaneous mount --move), and\nmove all processes with chdir or chroot under OLD into NEW (including\nkernel threads) so OLD may be unmounted.\n\nThe directory NEW must exist under OLD. This doesn't work on initramfs,\nwhich can't be moved (about the same way PID 1 can't be killed; see\nswitch_root instead)."
 
@@ -222,11 +228,13 @@
 
 #define HELP_oneit "usage: oneit [-prn3] [-c CONSOLE] [COMMAND...]\n\nSimple init program that runs a single supplied command line with a\ncontrolling tty (so CTRL-C can kill it).\n\n-c	Which console device to use (/dev/console doesn't do CTRL-C, etc)\n-p	Power off instead of rebooting when command exits\n-r	Restart child when it exits\n-n	No reboot, just relaunch command line\n-3	Write 32 bit PID of each exiting reparented process to fd 3 of child\n	(Blocking writes, child must read to avoid eventual deadlock.)\n\nSpawns a single child process (because PID 1 has signals blocked)\nin its own session, reaps zombies until the child exits, then\nreboots the system (or powers off with -p, or restarts the child with -r).\n\nResponds to SIGUSR1 by halting the system, SIGUSR2 by powering off,\nand SIGTERM or SIGINT reboot."
 
-#define HELP_nsenter "usage: nsenter [-t pid] [-F] [-i] [-m] [-n] [-p] [-u] [-U] COMMAND...\n\nRun COMMAND in an existing (set of) namespace(s).\n\n-t	PID to take namespaces from    (--target)\n-F	don't fork, even if -p is used (--no-fork)\n\nThe namespaces to switch are:\n\n-i	SysV IPC: message queues, semaphores, shared memory (--ipc)\n-m	Mount/unmount tree (--mount)\n-n	Network address, sockets, routing, iptables (--net)\n-p	Process IDs and init, will fork unless -F is used (--pid)\n-u	Host and domain names (--uts)\n-U	UIDs, GIDs, capabilities (--user)\n\nIf -t isn't specified, each namespace argument must provide a path\nto a namespace file, ala \"-i=/proc/$PID/ns/ipc\""
+#define HELP_nsenter "usage: nsenter [-t pid] [-F] [-i] [-m] [-n] [-p] [-u] [-U] COMMAND...\n\nRun COMMAND in an existing (set of) namespace(s).\n\n-a	Enter all supported namespaces (--all)\n-F	don't fork, even if -p is used (--no-fork)\n-t	PID to take namespaces from    (--target)\n\nThe namespaces to switch are:\n\n-C	Control groups (--cgroup)\n-i	SysV IPC: message queues, semaphores, shared memory (--ipc)\n-m	Mount/unmount tree (--mount)\n-n	Network address, sockets, routing, iptables (--net)\n-p	Process IDs and init, will fork unless -F is used (--pid)\n-u	Host and domain names (--uts)\n-U	UIDs, GIDs, capabilities (--user)\n\nIf -t isn't specified, each namespace argument must provide a path\nto a namespace file, ala \"-i=/proc/$PID/ns/ipc\""
 
-#define HELP_unshare "usage: unshare [-imnpuUr] COMMAND...\n\nCreate new container namespace(s) for this process and its children, so\nsome attribute is not shared with the parent process.\n\n-f	Fork command in the background (--fork)\n-i	SysV IPC (message queues, semaphores, shared memory) (--ipc)\n-m	Mount/unmount tree (--mount)\n-n	Network address, sockets, routing, iptables (--net)\n-p	Process IDs and init (--pid)\n-r	Become root (map current euid/egid to 0/0, implies -U) (--map-root-user)\n-u	Host and domain names (--uts)\n-U	UIDs, GIDs, capabilities (--user)\n\nA namespace allows a set of processes to have a different view of the\nsystem than other sets of processes."
+#define HELP_unshare "usage: unshare [-imnpuUr] COMMAND...\n\nCreate new container namespace(s) for this process and its children, allowing\nthe new set of processes to have a different view of the system than the\nparent process.\n\n-a	Unshare all supported namespaces\n-f	Fork command in the background (--fork)\n-r	Become root (map current euid/egid to 0/0, implies -U) (--map-root-user)\n\nAvailable namespaces:\n-C	Control groups (--cgroup)\n-i	SysV IPC (message queues, semaphores, shared memory) (--ipc)\n-m	Mount/unmount tree (--mount)\n-n	Network address, sockets, routing, iptables (--net)\n-p	Process IDs and init (--pid)\n-u	Host and domain names (--uts)\n-U	UIDs, GIDs, capabilities (--user)\n\nEach namespace can take an optional argument, a persistent mountpoint usable\nby the nsenter command to add new processes to that the namespace. (Specify\nmultiple namespaces to unshare separately, ala -c -i -m because -cim is -c\nwith persistent mount \"im\".)"
 
-#define HELP_nbd_client "usage: nbd-client [-ns] HOST PORT DEVICE\n\n-n	Do not fork into background\n-s	nbd swap support (lock server into memory)"
+#define HELP_nbd_server "usage: nbd-server [-r] FILE\n\nServe a Network Block Device from FILE on stdin/out (ala inetd).\n\n-r	Read only export"
+
+#define HELP_nbd_client "usage: nbd-client [-ns] [-b BLKSZ] HOST PORT DEVICE\n\n-b	Block size (default 4096)\n-n	Do not daemonize\n-s	nbd swap support (lock server into memory)"
 
 #define HELP_mountpoint "usage: mountpoint [-qd] DIR\n       mountpoint [-qx] DEVICE\n\nCheck whether the directory or device is a mountpoint.\n\n-q	Be quiet, return zero if directory is a mountpoint\n-d	Print major/minor device number of the directory\n-x	Print major/minor device number of the block device"
 
@@ -244,7 +252,7 @@
 
 #define HELP_lsusb "usage: lsusb [-i]\n\nList USB hosts/devices.\n\n-i	ID database (default /etc/usb.ids[.gz])"
 
-#define HELP_lspci "usage: lspci [-ekmn] [-i FILE]\n\nList PCI devices.\n\n-e  Extended (6 digit) class\n-i  ID database (default /etc/pci.ids[.gz])\n-k  Show kernel driver\n-m  Machine readable\n-n  Numeric output (-nn for both)"
+#define HELP_lspci "usage: lspci [-ekmn] [-i FILE]\n\nList PCI devices.\n\n-e	Extended (6 digit) class\n-i	ID database (default /etc/pci.ids[.gz])\n-k	Show kernel driver\n-m	Machine readable\n-n	Numeric output (-nn for both)\n-x	Hex dump of config space (64 bytes; -xxx for 256, -xxxx for 4096)"
 
 #define HELP_lsmod "usage: lsmod\n\nDisplay the currently loaded modules, their sizes and their dependencies."
 
@@ -264,13 +272,13 @@
 
 #define HELP_inotifyd "usage: inotifyd PROG FILE[:MASK] ...\n\nWhen a filesystem event matching MASK occurs to a FILE, run PROG as:\n\n  PROG EVENTS FILE [DIRFILE]\n\nIf PROG is \"-\" events are sent to stdout.\n\nThis file is:\n  a  accessed    c  modified    e  metadata change  w  closed (writable)\n  r  opened      D  deleted     M  moved            0  closed (unwritable)\n  u  unmounted   o  overflow    x  unwatchable\n\nA file in this directory is:\n  m  moved in    y  moved out   n  created          d  deleted\n\nWhen x event happens for all FILEs, inotifyd exits (after waiting for PROG)."
 
-#define HELP_i2cset "usage: i2cset [-fy] BUS CHIP ADDR VALUE... MODE\n\nWrite an i2c register. MODE is b for byte, w for 16-bit word, i for I2C block.\n\n-f	Force access to busy devices\n-y	Answer \"yes\" to confirmation prompts (for script use)"
+#define HELP_i2cset "usage: i2cset [-fy] BUS CHIP ADDR VALUE... MODE\n\nWrite an i2c register. MODE is b for byte, w for 16-bit word, i for I2C block.\n\n-f	Force access to busy devices\n-y	Skip confirmation prompts (yes to all)"
 
-#define HELP_i2cget "usage: i2cget [-fy] BUS CHIP ADDR\n\nRead an i2c register.\n\n-f	Force access to busy devices\n-y	Answer \"yes\" to confirmation prompts (for script use)"
+#define HELP_i2cget "usage: i2cget [-fy] BUS CHIP [ADDR]\n\nRead an i2c register.\n\n-f	Force access to busy devices\n-y	Skip confirmation prompts (yes to all)"
 
-#define HELP_i2cdump "usage: i2cdump [-fy] BUS CHIP\n\nDump i2c registers.\n\n-f	Force access to busy devices\n-y	Answer \"yes\" to confirmation prompts (for script use)"
+#define HELP_i2cdump "usage: i2cdump [-fy] BUS CHIP\n\nDump i2c registers.\n\n-f	Force access to busy devices\n-y	Skip confirmation prompts (yes to all)"
 
-#define HELP_i2cdetect "usage: i2cdetect [-aqry] BUS [FIRST LAST]\nusage: i2cdetect -F BUS\nusage: i2cdetect -l\n\nDetect i2c devices.\n\n-a	All addresses (0x00-0x7f rather than 0x03-0x77 or FIRST-LAST)\n-F	Show functionality\n-l	List available buses\n-q	Probe with SMBus Quick Write (default)\n-r	Probe with SMBus Read Byte\n-y	Answer \"yes\" to confirmation prompts (for script use)"
+#define HELP_i2cdetect "usage: i2cdetect [-aqry] BUS [FIRST LAST]\nusage: i2cdetect -F BUS\nusage: i2cdetect -l\n\nDetect i2c devices.\n\n-a	All addresses (0x00-0x7f rather than 0x03-0x77 or FIRST-LAST)\n-F	Show functionality\n-l	List available buses\n-q	Probe with SMBus Quick Write (default)\n-r	Probe with SMBus Read Byte\n-y	Skip confirmation prompts (yes to all)"
 
 #define HELP_hwclock "usage: hwclock [-rswtluf]\n\nGet/set the hardware clock.\n\n-f FILE	Use specified device file instead of /dev/rtc0 (--rtc)\n-l	Hardware clock uses localtime (--localtime)\n-r	Show hardware clock time (--show)\n-s	Set system time from hardware clock (--hctosys)\n-t	Set the system time based on the current timezone (--systz)\n-u	Hardware clock uses UTC (--utc)\n-w	Set hardware clock from system time (--systohc)"
 
@@ -302,7 +310,7 @@
 
 #define HELP_fallocate "usage: fallocate [-l size] [-o offset] file\n\nTell the filesystem to allocate space for a file."
 
-#define HELP_factor "usage: factor NUMBER...\n\nFactor integers."
+#define HELP_factor "usage: factor NUMBER...\n\nFactor integers.\n\n-h	Human readable: show repeated factors as x^n\n-x	Hexadecimal output"
 
 #define HELP_eject "usage: eject [-stT] [DEVICE]\n\nEject DEVICE or default /dev/cdrom\n\n-s	SCSI device\n-t	Close tray\n-T	Open/close tray (toggle)"
 
@@ -330,7 +338,7 @@
 
 #define HELP_fstype "usage: fstype DEV...\n\nPrint type of filesystem on a block device or image."
 
-#define HELP_blkid "usage: blkid [-s TAG] [-UL] DEV...\n\nPrint type, label and UUID of filesystem on a block device or image.\n\n-U	Show UUID only (or device with that UUID)\n-L	Show LABEL only (or device with that LABEL)\n-s TAG	Only show matching tags (default all)"
+#define HELP_blkid "usage: blkid [-o TYPE] [-s TAG] [-UL] DEV...\n\nPrint type, label and UUID of filesystem on a block device or image.\n\n-U	Show UUID only (or device with that UUID)\n-L	Show LABEL only (or device with that LABEL)\n-o TYPE	Output format (full, value, export)\n-s TAG	Only show matching tags (default all)"
 
 #define HELP_blkdiscard "usage: blkdiscard [-olszf] DEVICE\n\nDiscard device sectors.\n\n-o, --offset OFF	Byte offset to start discarding at (default 0)\n-l, --length LEN	Bytes to discard (default all)\n-s, --secure		Perform secure discard\n-z, --zeroout		Zero-fill rather than discard\n-f, --force		Disable check for mounted filesystem\n\nOFF and LEN must be aligned to the device sector size.\nBy default entire device is discarded.\nWARNING: All discarded data is permanently lost!"
 
@@ -346,13 +354,7 @@
 
 #define HELP_xzcat "usage: xzcat [filename...]\n\nDecompress listed files to stdout. Use stdin if no files listed."
 
-#define HELP_wget_openssl "Enable HTTPS support for wget by linking to OpenSSL."
-
-#define HELP_wget_libtls "Enable HTTPS support for wget by linking to LibTLS.\nSupports using libtls, libretls or libtls-bearssl."
-
-#define HELP_wget "usage: wget [OPTIONS]... [URL]\n    --max-redirect          maximum redirections allowed\n-d, --debug                 print lots of debugging information\n-O, --output-document=FILE  specify output filename\n-p, --post-data=DATA        send data in body of POST request\n\nexamples:\n  wget http://www.example.com"
-
-#define HELP_vi "usage: vi [-s script] FILE\n-s script: run script file\nVisual text editor. Predates the existence of standardized cursor keys,\nso the controls are weird and historical."
+#define HELP_vi "usage: vi [-s script] FILE\n\nVisual text editor. Predates the existence of standardized cursor keys,\nso the controls are weird and historical.\n\n-s script: run script file"
 
 #define HELP_userdel "usage: userdel [-r] USER\nusage: deluser [-r] USER\n\nDelete USER from the SYSTEM\n\n-r	remove home directory"
 
@@ -406,7 +408,7 @@
 
 #define HELP_cd "usage: cd [-PL] [-] [path]\n\nChange current directory. With no arguments, go $HOME. Sets $OLDPWD to\nprevious directory: cd - to return to $OLDPWD.\n\n-P	Physical path: resolve symlinks in path\n-L	Local path: .. trims directories off $PWD (default)"
 
-#define HELP_sh "usage: sh [-c command] [script]\n\nCommand shell.  Runs a shell script, or reads input interactively\nand responds to it.\n\n-c	command line to execute\n-i	interactive mode (default when STDIN is a tty)"
+#define HELP_sh "usage: sh [-c command] [script]\n\nCommand shell.  Runs a shell script, or reads input interactively\nand responds to it. Roughly compatible with \"bash\". Run \"help\" for\nlist of built-in commands.\n\n-c	command line to execute\n-i	interactive mode (default when STDIN is a tty)\n-s	don't run script (args set $* parameters but read commands from stdin)\n\nCommand shells parse each line of input (prompting when interactive), perform\nvariable expansion and redirection, execute commands (spawning child processes\nand background jobs), and perform flow control based on the return code.\n\nParsing:\n  syntax errors\n\nInteractive prompts:\n  line continuation\n\nVariable expansion:\n  Note: can cause syntax errors at runtime\n\nRedirection:\n  HERE documents (parsing)\n  Pipelines (flow control and job control)\n\nRunning commands:\n  process state\n  builtins\n    cd [[ ]] (( ))\n    ! : [ # TODO: help for these?\n    true false help echo kill printf pwd test\n  child processes\n\nJob control:\n  &    Background process\n  Ctrl-C kill process\n  Ctrl-Z suspend process\n  bg fg jobs kill\n\nFlow control:\n;    End statement (same as newline)\n&    Background process (returns true unless syntax error)\n&&   If this fails, next command fails without running\n||   If this succeeds, next command succeeds without running\n|    Pipelines! (Can of worms...)\nfor {name [in...]}|((;;)) do; BODY; done\nif TEST; then BODY; fi\nwhile TEST; do BODY; done\ncase a in X);; esac\n[[ TEST ]]\n((MATH))\n\nJob control:\n&    Background process\nCtrl-C kill process\nCtrl-Z suspend process\nbg fg jobs kill"
 
 #define HELP_route "usage: route [-ne] [-A [inet|inet6]] [add|del TARGET [OPTIONS]]\n\nDisplay, add or delete network routes in the \"Forwarding Information Base\",\nwhich send packets out a network interface to an address.\n\n-n	Show numerical addresses (no DNS lookups)\n-e	display netstat fields\n\nAssigning an address to an interface automatically creates an appropriate\nnetwork route (\"ifconfig eth0 10.0.2.15/8\" does \"route add 10.0.0.0/8 eth0\"\nfor you), although some devices (such as loopback) won't show it in the\ntable. For machines more than one hop away, you need to specify a gateway\n(ala \"route add default gw 10.0.2.2\").\n\nThe address \"default\" is a wildcard address (0.0.0.0/0) matching all\npackets without a more specific route.\n\nAvailable OPTIONS include:\nreject   - blocking route (force match failure)\ndev NAME - force matching packets out this interface (ala \"eth0\")\nnetmask  - old way of saying things like ADDR/24\ngw ADDR  - forward packets to gateway ADDR"
 
@@ -452,6 +454,18 @@
 
 #define HELP_groupadd "usage: groupadd [-S] [-g GID] [USER] GROUP\n\nAdd a group or add a user to a group\n\n  -g GID Group id\n  -S     Create a system group"
 
+#define HELP_gitcheckout "usage: gitcheckout <branch>\nA minimal git checkout."
+
+#define HELP_gitfetch "usage: gitfetch\nA minimal git fetch."
+
+#define HELP_gitremote "usage: gitremote URL\nA minimal git remote add origin."
+
+#define HELP_gitinit "usage: gitinit NAME\nA minimal git init."
+
+#define HELP_gitclone "usage: gitclone URL\nA minimal git clone."
+
+#define HELP_gitcompat "Enable git compatible repos instead of minimal clone downloader."
+
 #define HELP_getty "usage: getty [OPTIONS] BAUD_RATE[,BAUD_RATE]... TTY [TERMTYPE]\n\nWait for a modem to dial into serial port, adjust baud rate, call login.\n\n-h    Enable hardware RTS/CTS flow control\n-L    Set CLOCAL (ignore Carrier Detect state)\n-m    Get baud rate from modem's CONNECT status message\n-n    Don't prompt for login name\n-w    Wait for CR or LF before sending /etc/issue\n-i    Don't display /etc/issue\n-f ISSUE_FILE  Display ISSUE_FILE instead of /etc/issue\n-l LOGIN  Invoke LOGIN instead of /bin/login\n-t SEC    Terminate after SEC if no login name is read\n-I INITSTR  Send INITSTR before anything else\n-H HOST    Log HOST into the utmp file as the hostname"
 
 #define HELP_getopt "usage: getopt [OPTIONS] [--] ARG...\n\nParse command-line options for use in shell scripts.\n\n-a	Allow long options starting with a single -.\n-l OPTS	Specify long options.\n-n NAME	Command name for error messages.\n-o OPTS	Specify short options.\n-T	Test whether this is a modern getopt.\n-u	Output options unquoted."
@@ -468,7 +482,7 @@
 
 #define HELP_dumpleases "usage: dumpleases [-r|-a] [-f LEASEFILE]\n\nDisplay DHCP leases granted by udhcpd\n-f FILE,  Lease file\n-r        Show remaining time\n-a        Show expiration time"
 
-#define HELP_diff "usage: diff [-abBdiNqrTstw] [-L LABEL] [-S FILE] [-U LINES] FILE1 FILE2\n\n-a	Treat all files as text\n-b	Ignore changes in the amount of whitespace\n-B	Ignore changes whose lines are all blank\n-d	Try hard to find a smaller set of changes\n-i	Ignore case differences\n-L	Use LABEL instead of the filename in the unified header\n-N	Treat absent files as empty\n-q	Output only whether files differ\n-r	Recurse\n-S	Start with FILE when comparing directories\n-T	Make tabs line up by prefixing a tab when necessary\n-s	Report when two files are the same\n-t	Expand tabs to spaces in output\n-u	Unified diff\n-U	Output LINES lines of context\n-w	Ignore all whitespace\n\n--color              Colored output\n--strip-trailing-cr  Strip trailing '\\r's from input lines"
+#define HELP_diff "usage: diff [-abBdiNqrTstw] [-L LABEL] [-S FILE] [-U LINES] [-F REGEX ] FILE1 FILE2\n\n-a	Treat all files as text\n-b	Ignore changes in the amount of whitespace\n-B	Ignore changes whose lines are all blank\n-d	Try hard to find a smaller set of changes\n-F 	Show the most recent line matching the regex\n-i	Ignore case differences\n-L	Use LABEL instead of the filename in the unified header\n-N	Treat absent files as empty\n-q	Output only whether files differ\n-r	Recurse\n-S	Start with FILE when comparing directories\n-s	Report when two files are the same\n-T	Make tabs line up by prefixing a tab when necessary\n-t	Expand tabs to spaces in output\n-u	Unified diff\n-U	Output LINES lines of context\n-w	Ignore all whitespace\n\n--color     Color output   --strip-trailing-cr   Strip '\\r' from input lines\n--TYPE-line-format=FORMAT  Display TYPE (unchanged/old/new) lines using FORMAT\n  FORMAT uses printf integer escapes (ala %-2.4x) followed by LETTER: FELMNn\nSupported format specifiers are:\n* %l, the contents of the line, without the trailing newline\n* %L, the contents of the line, including the trailing newline\n* %%, the character '%'"
 
 #define HELP_dhcpd "usage: dhcpd [-46fS] [-i IFACE] [-P N] [CONFFILE]\n\n -f    Run in foreground\n -i Interface to use\n -S    Log to syslog too\n -P N  Use port N (default ipv4 67, ipv6 547)\n -4, -6    Run as a DHCPv4 or DHCPv6 server"
 
@@ -476,7 +490,7 @@
 
 #define HELP_dhcp "usage: dhcp [-fbnqvoCRB] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n            [-H HOSTNAME] [-V VENDOR] [-x OPT:VAL] [-O OPT]\n\n     Configure network dynamically using DHCP.\n\n   -i Interface to use (default eth0)\n   -p Create pidfile\n   -s Run PROG at DHCP events (default /usr/share/dhcp/default.script)\n   -B Request broadcast replies\n   -t Send up to N discover packets\n   -T Pause between packets (default 3 seconds)\n   -A Wait N seconds after failure (default 20)\n   -f Run in foreground\n   -b Background if lease is not obtained\n   -n Exit if lease is not obtained\n   -q Exit after obtaining lease\n   -R Release IP on exit\n   -S Log to syslog too\n   -a Use arping to validate offered address\n   -O Request option OPT from server (cumulative)\n   -o Don't request any options (unless -O is given)\n   -r Request this IP address\n   -x OPT:VAL  Include option OPT in sent packets (cumulative)\n   -F Ask server to update DNS mapping for NAME\n   -H Send NAME as client hostname (default none)\n   -V VENDOR Vendor identifier (default 'toybox VERSION')\n   -C Don't send MAC as client identifier\n   -v Verbose\n\n   Signals:\n   USR1  Renew current lease\n   USR2  Release current lease"
 
-#define HELP_dd "usage: dd [if=FILE] [of=FILE] [ibs=N] [obs=N] [iflag=FLAGS] [oflag=FLAGS]\n        [bs=N] [count=N] [seek=N] [skip=N]\n        [conv=notrunc|noerror|sync|fsync] [status=noxfer|none]\n\nCopy/convert files.\n\nif=FILE		Read from FILE instead of stdin\nof=FILE		Write to FILE instead of stdout\nbs=N		Read and write N bytes at a time\nibs=N		Input block size\nobs=N		Output block size\ncount=N		Copy only N input blocks\nskip=N		Skip N input blocks\nseek=N		Skip N output blocks\niflag=FLAGS	Set input flags\noflag=FLAGS	Set output flags\nconv=notrunc	Don't truncate output file\nconv=noerror	Continue after read errors\nconv=sync	Pad blocks with zeros\nconv=fsync	Physically write data out before finishing\nstatus=noxfer	Don't show transfer rate\nstatus=none	Don't show transfer rate or records in/out\n\nFLAGS is a comma-separated list of:\n\ncount_bytes	(iflag) interpret count=N in bytes, not blocks\nseek_bytes	(oflag) interpret seek=N in bytes, not blocks\nskip_bytes	(iflag) interpret skip=N in bytes, not blocks\n\nNumbers may be suffixed by c (*1), w (*2), b (*512), kD (*1000), k (*1024),\nMD (*1000*1000), M (*1024*1024), GD (*1000*1000*1000) or G (*1024*1024*1024)."
+#define HELP_dd "usage: dd [if|of=FILE] [ibs|obs|bs|count|seek|skip=N] [conv|status|iflag|oflag=FLAG[,FLAG...]]\n\nCopy/convert blocks of data from input to output, with the following\nkeyword=value modifiers (and their default values):\n\nif=FILE  Read FILE (stdin)          of=FILE  Write to FILE (stdout)\n   bs=N  Block size in bytes (512)  count=N  Stop after copying N blocks\n  ibs=N  Input block size (bs=)       obs=N  Output block size (bs=)\n skip=N  Skip N input blocks (0)     seek=N  Skip N output blocks (0)\n\nEach =N value accepts the normal unit suffixes (see toybox --help).\n\nThese modifiers take a comma separated list of potential options:\n\niflag=count_bytes,skip_bytes   count=N or skip=N is in bytes not blocks\noflag=seek_bytes,append        seek=N is in bytes, append output to file\nstatus=noxfer,none             don't show transfer rate, no summary info\nconv=\n  notrunc  Don't truncate output    noerror  Continue after read errors\n  sync     Zero pad short reads     fsync    Flush output to disk at end\n  sparse   Seek past zeroed output  excl     Fail if output file exists\n  nocreat  Fail if of=FILE missing"
 
 #define HELP_crontab "usage: crontab [-u user] FILE\n               [-u user] [-e | -l | -r]\n               [-c dir]\n\nFiles used to schedule the execution of programs.\n\n-c crontab dir\n-e edit user's crontab\n-l list user's crontab\n-r delete user's crontab\n-u user\nFILE Replace crontab by FILE ('-': stdin)"
 
@@ -486,7 +500,7 @@
 
 #define HELP_brctl "usage: brctl COMMAND [BRIDGE [INTERFACE]]\n\nManage ethernet bridges\n\nCommands:\nshow                  Show a list of bridges\naddbr BRIDGE          Create BRIDGE\ndelbr BRIDGE          Delete BRIDGE\naddif BRIDGE IFACE    Add IFACE to BRIDGE\ndelif BRIDGE IFACE    Delete IFACE from BRIDGE\nsetageing BRIDGE TIME Set ageing time\nsetfd BRIDGE TIME     Set bridge forward delay\nsethello BRIDGE TIME  Set hello time\nsetmaxage BRIDGE TIME Set max message age\nsetpathcost BRIDGE PORT COST   Set path cost\nsetportprio BRIDGE PORT PRIO   Set port priority\nsetbridgeprio BRIDGE PRIO      Set bridge priority\nstp BRIDGE [1/yes/on|0/no/off] STP on/off"
 
-#define HELP_bootchartd "usage: bootchartd {start [PROG ARGS]}|stop|init\n\nCreate /var/log/bootlog.tgz with boot chart data\n\nstart: start background logging; with PROG, run PROG,\n       then kill logging with USR1\nstop:  send USR1 to all bootchartd processes\ninit:  start background logging; stop when getty/xdm is seen\n      (for init scripts)\n\nUnder PID 1: as init, then exec $bootchart_init, /init, /sbin/init"
+#define HELP_bootchartd "usage: bootchartd {start [PROG ARGS]}|stop|init\n\nRecord boot chart data into /var/log/bootlog.tgz\n\nstart: start background logging; with PROG, run PROG,\n       then kill logging with SIGUSR1\nstop:  send SIGUSR1 to all bootchartd processes\ninit:  start background logging; stop when getty/xdm is seen\n      (for init scripts)\n\nUnder PID 1: as init, then exec $bootchart_init, /init, /sbin/init"
 
 #define HELP_bc "usage: bc [-ilqsw] [file ...]\n\nbc is a command-line calculator with a Turing-complete language.\n\noptions:\n\n  -i  --interactive  force interactive mode\n  -l  --mathlib      use predefined math routines:\n\n                     s(expr)  =  sine of expr in radians\n                     c(expr)  =  cosine of expr in radians\n                     a(expr)  =  arctangent of expr, returning radians\n                     l(expr)  =  natural log of expr\n                     e(expr)  =  raises e to the power of expr\n                     j(n, x)  =  Bessel function of integer order n of x\n\n  -q  --quiet        don't print version and copyright\n  -s  --standard     error if any non-POSIX extensions are used\n  -w  --warn         warn if any non-POSIX extensions are used"
 
@@ -524,11 +538,11 @@
 
 #define HELP_time "usage: time [-pv] COMMAND...\n\nRun command line and report real, user, and system time elapsed in seconds.\n(real = clock on the wall, user = cpu used by command's code,\nsystem = cpu used by OS on behalf of command.)\n\n-p	POSIX format output\n-v	Verbose"
 
-#define HELP_test "usage: test [-bcdefghLPrSsuwx PATH] [-nz STRING] [-t FD] [X ?? Y]\n\nReturn true or false by performing tests. (With no arguments return false.)\n\n--- Tests with a single argument (after the option):\nPATH is/has:\n  -b  block device   -f  regular file   -p  fifo           -u  setuid bit\n  -c  char device    -g  setgid         -r  read bit       -w  write bit\n  -d  directory      -h  symlink        -S  socket         -x  execute bit\n  -e  exists         -L  symlink        -s  nonzero size   -k  sticky bit\nSTRING is:\n  -n  nonzero size   -z  zero size      (STRING by itself implies -n)\nFD (integer file descriptor) is:\n  -t  a TTY\n\n--- Tests with one argument on each side of an operator:\nTwo strings:\n  =  are identical   !=  differ\n\nTwo integers:\n  -eq  equal         -gt  first > second    -lt  first < second\n  -ne  not equal     -ge  first >= second   -le  first <= second\n\n--- Modify or combine tests:\n  ! EXPR     not (swap true/false)   EXPR -a EXPR    and (are both true)\n  ( EXPR )   evaluate this first     EXPR -o EXPR    or (is either true)"
+#define HELP_test "usage: test [-bcdefghLPrSsuwx PATH] [-nz STRING] [-t FD] [X ?? Y]\n\nReturn true or false by performing tests. No arguments is false, one argument\nis true if not empty string.\n\n--- Tests with a single argument (after the option):\nPATH is/has:\n  -b  block device   -f  regular file   -p  fifo           -u  setuid bit\n  -c  char device    -g  setgid         -r  readable       -w  writable\n  -d  directory      -h  symlink        -S  socket         -x  executable\n  -e  exists         -L  symlink        -s  nonzero size   -k  sticky bit\nSTRING is:\n  -n  nonzero size   -z  zero size\nFD (integer file descriptor) is:\n  -t  a TTY          -T  open\n\n--- Tests with one argument on each side of an operator:\nTwo strings:\n  =  are identical   !=  differ         =~  string matches regex\nAlphabetical sort:\n  <  first is lower  >   first higher\nTwo integers:\n  -eq  equal         -gt  first > second    -lt  first < second\n  -ne  not equal     -ge  first >= second   -le  first <= second\n\n--- Modify or combine tests:\n  ! EXPR     not (swap true/false)   EXPR -a EXPR    and (are both true)\n  ( EXPR )   evaluate this first     EXPR -o EXPR    or (is either true)"
 
 #define HELP_tee "usage: tee [-ai] [FILE...]\n\nCopy stdin to each listed file, and also to stdout.\nFilename \"-\" is a synonym for stdout.\n\n-a	Append to files\n-i	Ignore SIGINT"
 
-#define HELP_tar "usage: tar [-cxt] [-fvohmjkOS] [-XTCf NAME] [--selinux] [FILE...]\n\nCreate, extract, or list files in a .tar (or compressed t?z) file.\n\nOptions:\nc  Create                x  Extract               t  Test (list)\nf  tar FILE (default -)  C  Change to DIR first   v  Verbose display\no  Ignore owner          h  Follow symlinks       m  Ignore mtime\nJ  xz compression        j  bzip2 compression     z  gzip compression\nO  Extract to stdout     X  exclude names in FILE T  include names in FILE\n\n--exclude        FILENAME to exclude  --full-time         Show seconds with -tv\n--mode MODE      Adjust permissions   --owner NAME[:UID]  Set file ownership\n--mtime TIME     Override timestamps  --group NAME[:GID]  Set file group\n--sparse         Record sparse files  --selinux           Save/restore labels\n--restrict       All under one dir    --no-recursion      Skip dir contents\n--numeric-owner  Use numeric uid/gid, not user/group names\n--strip-components NUM  Ignore first NUM directory components when extracting\n-I PROG          Filter through PROG to compress or PROG -d to decompress"
+#define HELP_tar "usage: tar [-cxt] [-fvohmjkOS] [-XTCf NAME] [--selinux] [FILE...]\n\nCreate, extract, or list files in a .tar (or compressed t?z) file.\n\nOptions:\nc  Create                x  Extract               t  Test (list)\nf  tar FILE (default -)  C  Change to DIR first   v  Verbose display\nJ  xz compression        j  bzip2 compression     z  gzip compression\no  Ignore owner          h  Follow symlinks       m  Ignore mtime\nO  Extract to stdout     X  exclude names in FILE T  include names in FILE\ns  Sort dirs (--sort)\n\n--exclude        FILENAME to exclude  --full-time         Show seconds with -tv\n--mode MODE      Adjust permissions   --owner NAME[:UID]  Set file ownership\n--mtime TIME     Override timestamps  --group NAME[:GID]  Set file group\n--sparse         Record sparse files  --selinux           Save/restore labels\n--restrict       All under one dir    --no-recursion      Skip dir contents\n--numeric-owner  Use numeric uid/gid, not user/group names\n--null           Filenames in -T FILE are null-separated, not newline\n--strip-components NUM  Ignore first NUM directory components when extracting\n--xform=SED      Modify filenames via SED expression (ala s/find/replace/g)\n-I PROG          Filter through PROG to compress or PROG -d to decompress\n\nFilename filter types. Create command line args aren't filtered, extract\ndefaults to --anchored, --exclude defaults to --wildcards-match-slash,\nuse no- prefix to disable:\n\n--anchored  Match name not path       --ignore-case       Case insensitive\n--wildcards Expand *?[] like shell    --wildcards-match-slash"
 
 #define HELP_tail "usage: tail [-n|c NUMBER] [-f|F] [-s SECONDS] [FILE...]\n\nCopy last lines from files to stdout. If no files listed, copy from\nstdin. Filename \"-\" is a synonym for stdin.\n\n-n	Output the last NUMBER lines (default 10), +X counts from start\n-c	Output the last NUMBER bytes, +NUMBER counts from start\n-f	Follow FILE(s) by descriptor, waiting for more data to be appended\n-F	Follow FILE(s) by filename, waiting for more data, and retrying\n-s	Used with -F, sleep SECONDS between retries (default 1)"
 
@@ -536,11 +550,11 @@
 
 #define HELP_split "usage: split [-a SUFFIX_LEN] [-b BYTES] [-l LINES] [-n PARTS] [INPUT [OUTPUT]]\n\nCopy INPUT (or stdin) data to a series of OUTPUT (or \"x\") files with\nalphabetically increasing suffix (aa, ab, ac... az, ba, bb...).\n\n-a	Suffix length (default 2)\n-b	BYTES/file (10, 10k, 10m, 10g...)\n-l	LINES/file (default 1000)\n-n	PARTS many equal length files"
 
-#define HELP_sort "usage: sort [-Mbcdfginrsuz] [FILE...] [-k#[,#[x]] [-t X]] [-o FILE]\n\nSort all lines of text from input files (or stdin) to stdout.\n-M	Month sort (jan, feb, etc)\n-V	Version numbers (name-1.234-rc6.5b.tgz)\n-b	Ignore leading blanks (or trailing blanks in second part of key)\n-c	Check whether input is sorted\n-d	Dictionary order (use alphanumeric and whitespace chars only)\n-f	Force uppercase (case insensitive sort)\n-g	General numeric sort (double precision with nan and inf)\n-i	Ignore nonprinting characters\n-k	Sort by \"key\" (see below)\n-n	Numeric order (instead of alphabetical)\n-o	Output to FILE instead of stdout\n-r	Reverse\n-s	Skip fallback sort (only sort with keys)\n-t	Use a key separator other than whitespace\n-u	Unique lines only\n-x	Hexadecimal numerical sort\n-z	Zero (null) terminated lines\n\nSorting by key looks at a subset of the words on each line. -k2 uses the\nsecond word to the end of the line, -k2,2 looks at only the second word,\n-k2,4 looks from the start of the second to the end of the fourth word.\n-k2.4,5 starts from the fourth character of the second word, to the end\nof the fifth word. Specifying multiple keys uses the later keys as tie\nbreakers, in order. A type specifier appended to a sort key (such as -2,2n)\napplies only to sorting that key."
+#define HELP_sort "usage: sort [-Mbcdfginrsuz] [FILE...] [-k#[,#[x]] [-t X]] [-o FILE]\n\nSort all lines of text from input files (or stdin) to stdout.\n-C	Check whether input is sorted\n-M	Month sort (jan, feb, etc)\n-V	Version numbers (name-1.234-rc6.5b.tgz)\n-b	Ignore leading blanks (or trailing blanks in second part of key)\n-c	Warn if input is unsorted\n-d	Dictionary order (use alphanumeric and whitespace chars only)\n-f	Force uppercase (case insensitive sort)\n-g	General numeric sort (double precision with nan and inf)\n-i	Ignore nonprinting characters\n-k	Sort by \"key\" (see below)\n-n	Numeric order (instead of alphabetical)\n-o	Output to FILE instead of stdout\n-r	Reverse\n-s	Skip fallback sort (only sort with keys)\n-t	Use a key separator other than whitespace\n-u	Unique lines only\n-x	Hexadecimal numerical sort\n-z	Zero (null) terminated lines\n\nSorting by key looks at a subset of the words on each line. -k2 uses the\nsecond word to the end of the line, -k2,2 looks at only the second word,\n-k2,4 looks from the start of the second to the end of the fourth word.\n-k2.4,5 starts from the fourth character of the second word, to the end\nof the fifth word. Specifying multiple keys uses the later keys as tie\nbreakers, in order. A type specifier appended to a sort key (such as -2,2n)\napplies only to sorting that key."
 
-#define HELP_sleep "usage: sleep DURATION\n\nWait before exiting.\n\nDURATION can be a decimal fraction. An optional suffix can be \"m\"\n(minutes), \"h\" (hours), \"d\" (days), or \"s\" (seconds, the default)."
+#define HELP_sleep "usage: sleep DURATION...\n\nWait before exiting.\n\nDURATION can be a decimal fraction. An optional suffix can be \"m\"\n(minutes), \"h\" (hours), \"d\" (days), or \"s\" (seconds, the default)."
 
-#define HELP_sed "usage: sed [-inrszE] [-e SCRIPT]...|SCRIPT [-f SCRIPT_FILE]... [FILE...]\n\nStream editor. Apply editing SCRIPTs to lines of input.\n\n-e	Add SCRIPT to list\n-f	Add contents of SCRIPT_FILE to list\n-i	Edit each file in place (-iEXT keeps backup file with extension EXT)\n-n	No default output (use the p command to output matched lines)\n-r	Use extended regular expression syntax\n-E	POSIX alias for -r\n-s	Treat input files separately (implied by -i)\n-z	Use \\0 rather than \\n as input line separator\n\nA SCRIPT is one or more COMMANDs separated by newlines or semicolons.\nAll -e SCRIPTs are combined as if separated by newlines, followed by all -f\nSCRIPT_FILEs. If no -e or -f then first argument is the SCRIPT.\n\nCOMMANDs apply to every line unless prefixed with an ADDRESS of the form:\n\n  [ADDRESS[,ADDRESS]][!]COMMAND\n\nADDRESS is a line number (starting at 1), a /REGULAR EXPRESSION/, or $ for\nlast line (-s or -i makes it last line of each file). One address matches one\nline, ADDRESS,ADDRESS matches from first to second inclusive. Two regexes can\nmatch multiple ranges. ADDRESS,+N ends N lines later. ! inverts the match.\n\nREGULAR EXPRESSIONS start and end with the same character (anything but\nbackslash or newline). To use the delimiter in the regex escape it with a\nbackslash, and printf escapes (\\abcefnrtv and octal, hex, and unicode) work.\nAn empty regex repeats the previous one. ADDRESS regexes require any\nfirst delimiter except / to be \\escaped to distinguish it from COMMANDs.\n\nSed reads each line of input, processes it, and writes it out or discards it\nbefore reading the next. Sed can remember one additional line in a separate\nbuffer (the h, H, g, G, and x commands), and can read the next line of input\nearly (the n and N commands), but otherwise operates on individual lines.\n\nEach COMMAND starts with a single character. Commands with no arguments are:\n\n  !  Run this command when the ADDRESS _didn't_ match.\n  {  Start new command block, continuing until a corresponding \"}\".\n     Command blocks nest and can have ADDRESSes applying to the whole block.\n  }  End command block (this COMMAND cannot have an address)\n  d  Delete this line and move on to the next one\n     (ignores remaining COMMANDs)\n  D  Delete one line of input and restart command SCRIPT (same as \"d\"\n     unless you've glued lines together with \"N\" or similar)\n  g  Get remembered line (overwriting current line)\n  G  Get remembered line (appending to current line)\n  h  Remember this line (overwriting remembered line)\n  H  Remember this line (appending to remembered line, if any)\n  l  Print line escaping \\abfrtv (but not \\n), octal escape other nonprintng\n     chars, wrap lines to terminal width with \\, append $ to end of line.\n  n  Print default output and read next line over current line (quit at EOF)\n  N  Append \\n and next line of input to this line. Quit at EOF without\n     default output. Advances line counter for ADDRESS and \"=\".\n  p  Print this line\n  P  Print this line up to first newline (from \"N\")\n  q  Quit (print default output, no more commands processed or lines read)\n  x  Exchange this line with remembered line (overwrite in both directions)\n  =  Print the current line number (plus newline)\n  #  Comment, ignores rest of this line of SCRIPT (until newline)\n\nCommands that take an argument:\n\n  : LABEL    Target for jump commands\n  a TEXT     Append text to output before reading next line\n  b LABEL    Branch, jumps to :LABEL (with no LABEL to end of SCRIPT)\n  c TEXT     Delete matching ADDRESS range and output TEXT instead\n  i TEXT     Insert text (output immediately)\n  r FILE     Append contents of FILE to output before reading next line.\n  s/S/R/F    Search for regex S replace match with R using flags F. Delimiter\n             is anything but \\n or \\, escape with \\ to use in S or R. Printf\n             escapes work. Unescaped & in R becomes full matched text, \\1\n             through \\9 = parenthetical subexpression from S. \\ at end of\n             line appends next line of SCRIPT. The flags in F are:\n             [0-9]    A number N, substitute only Nth match\n             g        Global, substitute all matches\n             i/I      Ignore case when matching\n             p        Print resulting line when match found and replaced\n             w [file] Write (append) line to file when match replaced\n  t LABEL    Test, jump if s/// command matched this line since last test\n  T LABEL    Test false, jump to :LABEL only if no s/// found a match\n  w FILE     Write (append) line to file\n  y/old/new/ Change each character in 'old' to corresponding character\n             in 'new' (with standard backslash escapes, delimiter can be\n             any repeated character except \\ or \\n)\n\nThe TEXT arguments (to a c i) may end with an unescaped \"\\\" to append\nthe next line (leading whitespace is not skipped), and treat \";\" as a\nliteral character (use \"\\;\" instead)."
+#define HELP_sed "usage: sed [-inrszE] [-e SCRIPT]...|SCRIPT [-f SCRIPT_FILE]... [FILE...]\n\nStream editor. Apply editing SCRIPTs to lines of input.\n\n-e	Add SCRIPT to list\n-f	Add contents of SCRIPT_FILE to list\n-i	Edit each file in place (-iEXT keeps backup file with extension EXT)\n-n	No default output (use the p command to output matched lines)\n-r	Use extended regular expression syntax\n-E	POSIX alias for -r\n-s	Treat input files separately (implied by -i)\n-z	Use \\0 rather than \\n as input line separator\n\nA SCRIPT is one or more COMMANDs separated by newlines or semicolons.\nAll -e SCRIPTs are combined as if separated by newlines, followed by all -f\nSCRIPT_FILEs. If no -e or -f then first argument is the SCRIPT.\n\nCOMMANDs apply to every line unless prefixed with an ADDRESS of the form:\n\n  [ADDRESS[,ADDRESS]][!]COMMAND\n\nADDRESS is a line number (starting at 1), a /REGULAR EXPRESSION/, or $ for\nlast line (-s or -i makes it last line of each file). One address matches one\nline, ADDRESS,ADDRESS matches from first to second inclusive. Two regexes can\nmatch multiple ranges. ADDRESS,+N ends N lines later. ! inverts the match.\n\nREGULAR EXPRESSIONS start and end with the same character (anything but\nbackslash or newline). To use the delimiter in the regex escape it with a\nbackslash, and printf escapes (\\abcefnrtv and octal, hex, and unicode) work.\nAn empty regex repeats the previous one. ADDRESS regexes require any\nfirst delimiter except / to be \\escaped to distinguish it from COMMANDs.\n\nSed reads each line of input, processes it, and writes it out or discards it\nbefore reading the next. Sed can remember one additional line in a separate\nbuffer (the h, H, g, G, and x commands), and can read the next line of input\nearly (the n and N commands), but otherwise operates on individual lines.\n\nEach COMMAND starts with a single character. Commands with no arguments are:\n\n  !  Run this command when the ADDRESS _didn't_ match.\n  {  Start new command block, continuing until a corresponding \"}\".\n     Command blocks nest and can have ADDRESSes applying to the whole block.\n  }  End command block (this COMMAND cannot have an address)\n  d  Delete this line and move on to the next one\n     (ignores remaining COMMANDs)\n  D  Delete one line of input and restart command SCRIPT (same as \"d\"\n     unless you've glued lines together with \"N\" or similar)\n  g  Get remembered line (overwriting current line)\n  G  Get remembered line (appending to current line)\n  h  Remember this line (overwriting remembered line)\n  H  Remember this line (appending to remembered line, if any)\n  l  Print line escaping \\abfrtvn, octal escape other nonprintng chars,\n     wrap lines to terminal width with \\, append $ to end of line.\n  n  Print default output and read next line over current line (quit at EOF)\n  N  Append \\n and next line of input to this line. Quit at EOF without\n     default output. Advances line counter for ADDRESS and \"=\".\n  p  Print this line\n  P  Print this line up to first newline (from \"N\")\n  q  Quit (print default output, no more commands processed or lines read)\n  x  Exchange this line with remembered line (overwrite in both directions)\n  =  Print the current line number (plus newline)\n  #  Comment, ignores rest of this line of SCRIPT (until newline)\n\nCommands that take an argument:\n\n  : LABEL    Target for jump commands\n  a TEXT     Append text to output before reading next line\n  b LABEL    Branch, jumps to :LABEL (with no LABEL to end of SCRIPT)\n  c TEXT     Delete matching ADDRESS range and output TEXT instead\n  i TEXT     Insert text (output immediately)\n  r FILE     Append contents of FILE to output before reading next line.\n  s/S/R/F    Search for regex S replace match with R using flags F. Delimiter\n             is anything but \\n or \\, escape with \\ to use in S or R. Printf\n             escapes work. Unescaped & in R becomes full matched text, \\1\n             through \\9 = parenthetical subexpression from S. \\ at end of\n             line appends next line of SCRIPT. The flags in F are:\n             [0-9]    A number N, substitute only Nth match\n             g        Global, substitute all matches\n             i/I      Ignore case when matching\n             p        Print resulting line when match found and replaced\n             w [file] Write (append) line to file when match replaced\n  t LABEL    Test, jump if s/// command matched this line since last test\n  T LABEL    Test false, jump to :LABEL only if no s/// found a match\n  w FILE     Write (append) line to file\n  y/old/new/ Change each character in 'old' to corresponding character\n             in 'new' (with standard backslash escapes, delimiter can be\n             any repeated character except \\ or \\n)\n\nThe TEXT arguments (to a c i) may end with an unescaped \"\\\" to append\nthe next line (leading whitespace is not skipped), and treat \";\" as a\nliteral character (use \"\\;\" instead)."
 
 #define HELP_rmdir "usage: rmdir [-p] [DIR...]\n\nRemove one or more directories.\n\n-p	Remove path\n--ignore-fail-on-non-empty	Ignore failures caused by non-empty directories"
 
@@ -580,7 +594,7 @@
 
 #define HELP_mkdir "usage: mkdir [-vp] [-m MODE] [DIR...]\n\nCreate one or more directories.\n\n-m	Set permissions of directory to mode\n-p	Make parent directories as needed\n-v	Verbose"
 
-#define HELP_ls "usage: ls [-ACFHLRSZacdfhiklmnpqrstuwx1] [--color[=auto]] [FILE...]\n\nList files.\n\nwhat to show:\n-a  all files including .hidden    -b  escape nongraphic chars\n-c  use ctime for timestamps       -d  directory, not contents\n-i  inode number                   -p  put a '/' after dir names\n-q  unprintable chars as '?'       -s  storage used (1024 byte units)\n-u  use access time for timestamps -A  list all files but . and ..\n-H  follow command line symlinks   -L  follow symlinks\n-R  recursively list in subdirs    -F  append /dir *exe @sym |FIFO\n-Z  security context\n\noutput formats:\n-1  list one file per line         -C  columns (sorted vertically)\n-g  like -l but no owner           -h  human readable sizes\n-l  long (show full details)       -m  comma separated\n-n  like -l but numeric uid/gid    -o  like -l but no group\n-w  set column width               -x  columns (horizontal sort)\n-ll long with nanoseconds (--full-time)\n--color  device=yellow  symlink=turquoise/red  dir=blue  socket=purple\n         files: exe=green  suid=red  suidfile=redback  stickydir=greenback\n         =auto means detect if output is a tty.\n\nsorting (default is alphabetical):\n-f  unsorted    -r  reverse    -t  timestamp    -S  size"
+#define HELP_ls "usage: ls [-1ACFHLNRSUXZabcdfghilmnopqrstuwx] [--color[=auto]] [FILE...]\n\nList files\n\nwhat to show:\n-A  all files except . and ..      -a  all files including .hidden\n-b  escape nongraphic chars        -d  directory, not contents\n-F  append /dir *exe @sym |FIFO    -f  files (no sort/filter/format)\n-H  follow command line symlinks   -i  inode number\n-L  follow symlinks                -N  no escaping, even on tty\n-p  put '/' after dir names        -q  unprintable chars as '?'\n-R  recursively list in subdirs    -s  storage used (1024 byte units)\n-Z  security context\n\noutput formats:\n-1  list one file per line         -C  columns (sorted vertically)\n-g  like -l but no owner           -h  human readable sizes\n-l  long (show full details)       -ll long with nanoseconds (--full-time)\n-m  comma separated                -n  long with numeric uid/gid\n-o  long without group column      -r  reverse order\n-w  set column width               -x  columns (horizontal sort)\n\nsort by:  (also --sort=longname,longname... ends with alphabetical)\n-c  ctime      -r  reverse    -S  size     -t  time    -u  atime    -U  none\n-X  extension  -!  dirfirst   -~  nocase\n\n--color  =always (default)  =auto (when stdout is tty) =never\n    exe=green  suid=red  suidfile=redback  stickydir=greenback\n    device=yellow  symlink=turquoise/red  dir=blue  socket=purple\n\nLong output uses -cu for display, use -ltc/-ltu to also sort by ctime/atime."
 
 #define HELP_logger "usage: logger [-s] [-t TAG] [-p [FACILITY.]PRIORITY] [MESSAGE...]\n\nLog message (or stdin) to syslog.\n\n-s	Also write message to stderr\n-t	Use TAG instead of username to identify message source\n-p	Specify PRIORITY with optional FACILITY. Default is \"user.notice\""
 
@@ -608,7 +622,7 @@
 
 #define HELP_getconf "usage: getconf -a [PATH] | -l | NAME [PATH]\n\nGet system configuration values. Values from pathconf(3) require a path.\n\n-a	Show all (defaults to \"/\" if no path given)\n-l	List available value names (grouped by source)"
 
-#define HELP_find "usage: find [-HL] [DIR...] [<options>]\n\nSearch directories for matching files.\nDefault: search \".\", match all, -print matches.\n\n-H  Follow command line symlinks         -L  Follow all symlinks\n\nMatch filters:\n-name  PATTERN   filename with wildcards   -iname      ignore case -name\n-path  PATTERN   path name with wildcards  -ipath      ignore case -path\n-user  UNAME     belongs to user UNAME     -nouser     user ID not known\n-group GROUP     belongs to group GROUP    -nogroup    group ID not known\n-perm  [-/]MODE  permissions (-=min /=any) -prune      ignore dir contents\n-size  N[c]      512 byte blocks (c=bytes) -xdev       only this filesystem\n-links N         hardlink count            -atime N[u] accessed N units ago\n-ctime N[u]      created N units ago       -mtime N[u] modified N units ago\n-inum N          inode number N            -empty      empty files and dirs\n-true            always true               -false      always false\n-context PATTERN security context          -executable access(X_OK) perm+ACL\n-samefile FILE   hardlink to FILE          -quit       exit immediately\n-depth           ignore contents of dir    -maxdepth N at most N dirs down\n-newer FILE      newer mtime than FILE     -mindepth N at least N dirs down\n-newerXY FILE    X=acm time > FILE's Y=acm time (Y=t: FILE is literal time)\n-type [bcdflps]  type is (block, char, dir, file, symlink, pipe, socket)\n\nNumbers N may be prefixed by a - (less than) or + (greater than). Units for\n-Xtime are d (days, default), h (hours), m (minutes), or s (seconds).\n\nCombine matches with:\n!, -a, -o, ( )    not, and, or, group expressions\n\nActions:\n-print  Print match with newline  -print0        Print match with null\n-exec   Run command with path     -execdir       Run command in file's dir\n-ok     Ask before exec           -okdir         Ask before execdir\n-delete Remove matching file/dir  -printf FORMAT Print using format string\n\nCommands substitute \"{}\" with matched file. End with \";\" to run each file,\nor \"+\" (next argument after \"{}\") to collect and run with multiple files.\n\n-printf FORMAT characters are \\ escapes and:\n%b  512 byte blocks used\n%f  basename            %g  textual gid          %G  numeric gid\n%i  decimal inode       %l  target of symlink    %m  octal mode\n%M  ls format type/mode %p  path to file         %P  path to file minus DIR\n%s  size in bytes       %T@ mod time as unixtime\n%u  username            %U  numeric uid          %Z  security context"
+#define HELP_find "usage: find [-HL] [DIR...] [<options>]\n\nSearch directories for matching files.\nDefault: search \".\", match all, -print matches.\n\n-H  Follow command line symlinks         -L  Follow all symlinks\n\nMatch filters:\n-name  PATTERN   filename with wildcards   -iname      ignore case -name\n-path  PATTERN   path name with wildcards  -ipath      ignore case -path\n-user  UNAME     belongs to user UNAME     -nouser     user ID not known\n-group GROUP     belongs to group GROUP    -nogroup    group ID not known\n-perm  [-/]MODE  permissions (-=min /=any) -prune      ignore dir contents\n-size  N[c]      512 byte blocks (c=bytes) -xdev       only this filesystem\n-links N         hardlink count            -empty      empty files and dirs\n-atime N[u]      accessed N units ago      -true       always true\n-ctime N[u]      created N units ago       -false      always false\n-mtime N[u]      modified N units ago      -executable access(X_OK) perm+ACL\n-inum  N         inode number N            -readable   access(R_OK) perm+ACL\n-context PATTERN security context          -depth      contents before dir\n-samefile FILE   hardlink to FILE          -maxdepth N at most N dirs down\n-newer    FILE   newer mtime than FILE     -mindepth N at least N dirs down\n-newerXY  FILE   X=acm time > FILE's Y=acm time (Y=t: FILE is literal time)\n-type [bcdflps]  type is (block, char, dir, file, symlink, pipe, socket)\n\nNumbers N may be prefixed by - (less than) or + (greater than). Units for\n-[acm]time are d (days, default), h (hours), m (minutes), or s (seconds).\n\nCombine matches with:\n!, -a, -o, ( )    not, and, or, group expressions\n\nActions:\n-print  Print match with newline  -print0        Print match with null\n-exec   Run command with path     -execdir       Run command in file's dir\n-ok     Ask before exec           -okdir         Ask before execdir\n-delete Remove matching file/dir  -printf FORMAT Print using format string\n-quit   Exit immediately\n\nCommands substitute \"{}\" with matched file. End with \";\" to run each file,\nor \"+\" (next argument after \"{}\") to collect and run with multiple files.\n\n-printf FORMAT characters are \\ escapes and:\n%b  512 byte blocks used\n%f  basename            %g  textual gid          %G  numeric gid\n%i  decimal inode       %l  target of symlink    %m  octal mode\n%M  ls format type/mode %p  path to file         %P  path to file minus DIR\n%s  size in bytes       %T@ mod time as unixtime\n%u  username            %U  numeric uid          %Z  security context"
 
 #define HELP_file "usage: file [-bhLs] [FILE...]\n\nExamine the given files and describe their content types.\n\n-b	Brief (no filename)\n-h	Don't follow symlinks (default)\n-L	Follow symlinks\n-s	Show block/char device contents"
 
@@ -628,9 +642,9 @@
 
 #define HELP_date "usage: date [-u] [-I RES] [-r FILE] [-d DATE] [+DISPLAY_FORMAT] [-D SET_FORMAT] [SET]\n\nSet/get the current date/time. With no SET shows the current date.\n\n-d	Show DATE instead of current time (convert date format)\n-D	+FORMAT for SET or -d (instead of MMDDhhmm[[CC]YY][.ss])\n-I RES	ISO 8601 with RESolution d=date/h=hours/m=minutes/s=seconds/n=ns\n-r	Use modification time of FILE instead of current date\n-s DATE	Set the system clock to DATE.\n-u	Use UTC instead of current timezone\n\nSupported input formats:\n\nMMDDhhmm[[CC]YY][.ss]     POSIX\n@UNIXTIME[.FRACTION]      seconds since midnight 1970-01-01\nYYYY-MM-DD [hh:mm[:ss]]   ISO 8601\nhh:mm[:ss]                24-hour time today\n\nAll input formats can be followed by fractional seconds, and/or a UTC\noffset such as -0800.\n\nAll input formats can be preceded by TZ=\"id\" to set the input time zone\nseparately from the output time zone. Otherwise $TZ sets both.\n\n+FORMAT specifies display format string using strftime(3) syntax:\n\n%% literal %             %n newline              %t tab\n%S seconds (00-60)       %M minute (00-59)       %m month (01-12)\n%H hour (0-23)           %I hour (01-12)         %p AM/PM\n%y short year (00-99)    %Y year                 %C century\n%a short weekday name    %A weekday name         %u day of week (1-7, 1=mon)\n%b short month name      %B month name           %Z timezone name\n%j day of year (001-366) %d day of month (01-31) %e day of month ( 1-31)\n%N nanosec (output only)\n\n%U Week of year (0-53 start Sunday)   %W Week of year (0-53 start Monday)\n%V Week of year (1-53 start Monday, week < 4 days not part of this year)\n\n%F \"%Y-%m-%d\"   %R \"%H:%M\"        %T \"%H:%M:%S\"        %z  timezone (-0800)\n%D \"%m/%d/%y\"   %r \"%I:%M:%S %p\"  %h \"%b\"              %:z timezone (-08:00)\n%x locale date  %X locale time    %c locale date/time  %s  unix epoch time"
 
-#define HELP_cut "usage: cut [-Ds] [-bcCfF LIST] [-dO DELIM] [FILE...]\n\nPrint selected parts of lines from each FILE to standard output.\n\nEach selection LIST is comma separated, either numbers (counting from 1)\nor dash separated ranges (inclusive, with X- meaning to end of line and -X\nfrom start). By default selection ranges are sorted and collated, use -D\nto prevent that.\n\n-b	Select bytes\n-c	Select UTF-8 characters\n-C	Select unicode columns\n-d	Use DELIM (default is TAB for -f, run of whitespace for -F)\n-D	Don't sort/collate selections or match -fF lines without delimiter\n-f	Select fields (words) separated by single DELIM character\n-F	Select fields separated by DELIM regex\n-O	Output delimiter (default one space for -F, input delim for -f)\n-s	Skip lines without delimiters"
+#define HELP_cut "usage: cut [-Ds] [-bcCfF LIST] [-dO DELIM] [FILE...]\n\nPrint selected parts of lines from each FILE to standard output.\n\nEach selection LIST is comma separated, either numbers (counting from 1)\nor dash separated ranges (inclusive, with X- meaning to end of line and -X\nfrom start). By default selection ranges are sorted and collated, use -D\nto prevent that.\n\n-b	Select bytes (with -n round start/end down to start of utf8 char)\n-c	Select UTF-8 characters\n-C	Select unicode columns\n-d	Use DELIM (default is TAB for -f, run of whitespace for -F)\n-D	Don't sort/collate selections or match -fF lines without delimiter\n-f	Select fields (words) separated by single DELIM character\n-F	Select fields separated by DELIM regex\n-O	Output delimiter (default one space for -F, input delim for -f)\n-s	Skip lines without delimiters"
 
-#define HELP_cpio "usage: cpio -{o|t|i|p DEST} [-v] [--verbose] [-F FILE] [--no-preserve-owner]\n       [ignored: -m -H newc]\n\nCopy files into and out of a \"newc\" format cpio archive.\n\n-F FILE	Use archive FILE instead of stdin/stdout\n-p DEST	Copy-pass mode, copy stdin file list to directory DEST\n-i	Extract from archive into file system (stdin=archive)\n-o	Create archive (stdin=list of files, stdout=archive)\n-t	Test files (list only, stdin=archive, stdout=list of files)\n-d	Create directories if needed\n-u	unlink existing files when extracting\n-v	Verbose\n--no-preserve-owner (don't set ownership during extract)"
+#define HELP_cpio "usage: cpio -{o|t|i|p DEST} [-v] [--verbose] [-F FILE] [-R [USER][:GROUP] [--no-preserve-owner]\n\nCopy files into and out of a \"newc\" format cpio archive.\n\n-d	Create directories if needed\n-F FILE	Use archive FILE instead of stdin/stdout\n-i	Extract from archive into file system (stdin=archive)\n-o	Create archive (stdin=list of files, stdout=archive)\n-p DEST	Copy-pass mode, copy stdin file list to directory DEST\n-R USER	Replace owner with USER[:GROUP]\n-t	Test files (list only, stdin=archive, stdout=list of files)\n-u	Unlink existing files when extracting\n-v	Verbose\n--no-preserve-owner     Don't set ownership during extract"
 
 #define HELP_install "usage: install [-dDpsv] [-o USER] [-g GROUP] [-m MODE] [-t TARGET] [SOURCE...] [DEST]\n\nCopy files and set attributes.\n\n-d	Act like mkdir -p\n-D	Create leading directories for DEST\n-g	Make copy belong to GROUP\n-m	Set permissions to MODE\n-o	Make copy belong to USER\n-p	Preserve timestamps\n-s	Call \"strip -p\"\n-t	Copy files to TARGET dir (no DEST)\n-v	Verbose"
 
@@ -652,8 +666,6 @@
 
 #define HELP_chgrp "usage: chgrp/chown [-RHLP] [-fvh] GROUP FILE...\n\nChange group of one or more files.\n\n-f	Suppress most error messages\n-h	Change symlinks instead of what they point to\n-R	Recurse into subdirectories (implies -h)\n-H	With -R change target of symlink, follow command line symlinks\n-L	With -R change target of symlink, follow all symlinks\n-P	With -R change symlink, do not follow symlinks (default)\n-v	Verbose"
 
-#define HELP_catv "usage: catv [-evt] [FILE...]\n\nDisplay nonprinting characters as escape sequences. Use M-x for\nhigh ascii characters (>127), and ^x for other nonprinting chars.\n\n-e	Mark each newline with $\n-t	Show tabs as ^I\n-v	Don't use ^x or M-x escapes"
-
 #define HELP_cat "usage: cat [-etuv] [FILE...]\n\nCopy (concatenate) files to stdout.  If no files listed, copy from stdin.\nFilename \"-\" is a synonym for stdin.\n\n-e	Mark each newline with $\n-t	Show tabs as ^I\n-u	Copy one byte at a time (slow)\n-v	Display nonprinting characters as escape sequences with M-x for\n	high ascii characters (>127), and ^x for other nonprinting chars"
 
 #define HELP_cal "usage: cal [[[DAY] MONTH] YEAR]\n\nPrint a calendar.\n\nWith one argument, prints all months of the specified year.\nWith two arguments, prints calendar for month and year.\nWith three arguments, highlights day within month and year.\n\n-h	Don't highlight today"
diff --git a/android/device/generated/newtoys.h b/android/device/generated/newtoys.h
index ade8831..0680e5d 100644
--- a/android/device/generated/newtoys.h
+++ b/android/device/generated/newtoys.h
@@ -1,10 +1,11 @@
-USE_TOYBOX(NEWTOY(toybox, NULL, TOYFLAG_STAYROOT|TOYFLAG_NOHELP))
+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_ACPI(NEWTOY(acpi, "abctV", TOYFLAG_USR|TOYFLAG_BIN))
 USE_GROUPADD(OLDTOY(addgroup, groupadd, TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
 USE_USERADD(OLDTOY(adduser, useradd, TOYFLAG_NEEDROOT|TOYFLAG_UMASK|TOYFLAG_SBIN))
@@ -12,21 +13,20 @@
 USE_ARP(NEWTOY(arp, "vi:nDsdap:A:H:[+Ap][!sd]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_ARPING(NEWTOY(arping, "<1>1s:I:w#<0c#<0AUDbqf[+AU][+Df]", TOYFLAG_USR|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))
-USE_BASE64(NEWTOY(base64, "diw#<0=76[!dw]", TOYFLAG_USR|TOYFLAG_BIN))
+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_BC(NEWTOY(bc, "i(interactive)l(mathlib)q(quiet)s(standard)w(warn)", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
 USE_BLKDISCARD(NEWTOY(blkdiscard, "<1>1f(force)l(length)#<0o(offset)#<0s(secure)z(zeroout)[!sz]", TOYFLAG_BIN))
-USE_BLKID(NEWTOY(blkid, "ULs*[!LU]", TOYFLAG_BIN))
+USE_BLKID(NEWTOY(blkid, "ULo:s*[!LU]", TOYFLAG_BIN))
 USE_BLOCKDEV(NEWTOY(blockdev, "<1>1(setro)(setrw)(getro)(getss)(getbsz)(setbsz)#<0(getsz)(getsize)(getsize64)(getra)(setra)#<0(flushbufs)(rereadpt)",TOYFLAG_SBIN))
 USE_BOOTCHARTD(NEWTOY(bootchartd, 0, TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
 USE_BRCTL(NEWTOY(brctl, "<1", TOYFLAG_USR|TOYFLAG_SBIN))
 USE_BUNZIP2(NEWTOY(bunzip2, "cftkv", TOYFLAG_USR|TOYFLAG_BIN))
 USE_BZCAT(NEWTOY(bzcat, NULL, TOYFLAG_USR|TOYFLAG_BIN))
 USE_CAL(NEWTOY(cal, ">3h", TOYFLAG_USR|TOYFLAG_BIN))
-USE_CAT(NEWTOY(cat, "u"USE_CAT_V("vte"), TOYFLAG_BIN))
-USE_CATV(NEWTOY(catv, USE_CATV("vte"), TOYFLAG_USR|TOYFLAG_BIN))
+USE_CAT(NEWTOY(cat, "uvte", TOYFLAG_BIN))
 USE_SH(NEWTOY(cd, ">1LP[-LP]", TOYFLAG_NOFORK))
 USE_CHATTR(NEWTOY(chattr, "?p#v#R", TOYFLAG_BIN))
 USE_CHCON(NEWTOY(chcon, "<2hvR", TOYFLAG_USR|TOYFLAG_BIN))
@@ -36,19 +36,19 @@
 USE_CHROOT(NEWTOY(chroot, "^<1", TOYFLAG_USR|TOYFLAG_SBIN|TOYFLAG_ARGFAIL(125)))
 USE_CHRT(NEWTOY(chrt, "^mp#<0iRbrfo[!ibrfo]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_CHSH(NEWTOY(chsh, "s:", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
-USE_CHVT(NEWTOY(chvt, "<1", TOYFLAG_USR|TOYFLAG_BIN))
+USE_CHVT(NEWTOY(chvt, "<1>1", TOYFLAG_USR|TOYFLAG_BIN))
 USE_CKSUM(NEWTOY(cksum, "HIPLN", TOYFLAG_BIN))
 USE_CLEAR(NEWTOY(clear, NULL, TOYFLAG_USR|TOYFLAG_BIN))
 USE_CMP(NEWTOY(cmp, "<1>4ls(silent)(quiet)n#<1[!ls]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
 USE_COMM(NEWTOY(comm, "<2>2321", TOYFLAG_USR|TOYFLAG_BIN))
 USE_COUNT(NEWTOY(count, NULL, TOYFLAG_USR|TOYFLAG_BIN))
 USE_CP(NEWTOY(cp, "<1(preserve):;D(parents)RHLPprudaslvnF(remove-destination)fit:T[-HLPd][-niu][+Rr]", TOYFLAG_BIN))
-USE_CPIO(NEWTOY(cpio, "(ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]", TOYFLAG_BIN))
+USE_CPIO(NEWTOY(cpio, "(ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)R(owner):md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]", TOYFLAG_BIN))
 USE_CRC32(NEWTOY(crc32, 0, TOYFLAG_BIN))
 USE_CROND(NEWTOY(crond, "fbSl#<0=8d#<0L:c:[-bf][-LS][-ld]", TOYFLAG_USR|TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
 USE_CRONTAB(NEWTOY(crontab, "c:u:elr[!elr]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
-USE_CUT(NEWTOY(cut, "b*|c*|f*|F*|C*|O(output-delimiter):d:sDn[!cbfF]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_DATE(NEWTOY(date, "d:D:I(iso)(iso-8601):;r:s:u(utc)[!dr]", TOYFLAG_BIN))
+USE_CUT(NEWTOY(cut, "b*|c*|f*|F(regex-fields)*|C*|O(output-delimiter):d:sD(allow-duplicates)n[!cbfF]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_DATE(NEWTOY(date, "d:D:I(iso-8601):;r:s:u(utc)[!dr]", TOYFLAG_BIN))
 USE_DD(NEWTOY(dd, 0, TOYFLAG_USR|TOYFLAG_BIN))
 USE_DEALLOCVT(NEWTOY(deallocvt, ">1", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_NEEDROOT))
 USE_SH(NEWTOY(declare, "pAailunxr", TOYFLAG_NOFORK))
@@ -58,12 +58,12 @@
 USE_DEMO_NUMBER(NEWTOY(demo_number, "D#=3<3M#<0hcdbs", TOYFLAG_BIN))
 USE_DEMO_SCANKEY(NEWTOY(demo_scankey, 0, TOYFLAG_BIN))
 USE_DEMO_UTF8TOWC(NEWTOY(demo_utf8towc, 0, TOYFLAG_USR|TOYFLAG_BIN))
-USE_DEVMEM(NEWTOY(devmem, "<1>3", TOYFLAG_USR|TOYFLAG_BIN))
-USE_DF(NEWTOY(df, "HPkhit*a[-HPh]", TOYFLAG_SBIN))
+USE_DEVMEM(NEWTOY(devmem, "<1>3", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_DF(NEWTOY(df, "HPkhit*a[-HPh]", TOYFLAG_BIN))
 USE_DHCP(NEWTOY(dhcp, "V:H:F:x*r:O*A#<0=20T#<0=3t#<0=3s:p:i:SBRCaovqnbf", TOYFLAG_SBIN|TOYFLAG_ROOTONLY))
 USE_DHCP6(NEWTOY(dhcp6, "r:A#<0T#<0t#<0s:p:i:SRvqnbf", TOYFLAG_SBIN|TOYFLAG_ROOTONLY))
 USE_DHCPD(NEWTOY(dhcpd, ">1P#<0>65535fi:S46[!46]", TOYFLAG_SBIN|TOYFLAG_ROOTONLY))
-USE_DIFF(NEWTOY(diff, "<2>2(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)L(label)*S(starting-file):N(new-file)r(recursive)U(unified)#<0=3", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
+USE_DIFF(NEWTOY(diff, "<2>2(unchanged-line-format):;(old-line-format):;(new-line-format):;(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)S(starting-file):F(show-function-line):;L(label)*N(new-file)r(recursive)U(unified)#<0=3", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
 USE_DIRNAME(NEWTOY(dirname, "<1", TOYFLAG_USR|TOYFLAG_BIN))
 USE_DMESG(NEWTOY(dmesg, "w(follow)CSTtrs#<1n#c[!Ttr][!Cc][!Sw]", TOYFLAG_BIN))
 USE_DNSDOMAINNAME(NEWTOY(dnsdomainname, ">0", TOYFLAG_BIN))
@@ -80,12 +80,12 @@
 USE_EXPAND(NEWTOY(expand, "t*", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
 USE_SH(NEWTOY(export, "np", TOYFLAG_NOFORK))
 USE_EXPR(NEWTOY(expr, NULL, TOYFLAG_USR|TOYFLAG_BIN))
-USE_FACTOR(NEWTOY(factor, 0, TOYFLAG_USR|TOYFLAG_BIN))
+USE_FACTOR(NEWTOY(factor, "?hx", TOYFLAG_USR|TOYFLAG_BIN))
 USE_FALLOCATE(NEWTOY(fallocate, ">1l#|o#", TOYFLAG_USR|TOYFLAG_BIN))
 USE_FALSE(NEWTOY(false, NULL, TOYFLAG_BIN|TOYFLAG_NOHELP|TOYFLAG_MAYFORK))
 USE_FDISK(NEWTOY(fdisk, "C#<0H#<0S#<0b#<512ul", TOYFLAG_SBIN))
 USE_FGREP(OLDTOY(fgrep, grep, TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)|TOYFLAG_LINEBUF))
-USE_FILE(NEWTOY(file, "<1bhLs[!hL]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_FILE(NEWTOY(file, "<1b(brief)hLs[!hL]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_FIND(NEWTOY(find, "?^HL[-HL]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_FLOCK(NEWTOY(flock, "<1>1nsux[-sux]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_FMT(NEWTOY(fmt, "w#<0=75", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
@@ -103,17 +103,22 @@
 USE_GETFATTR(NEWTOY(getfattr, "(only-values)dhn:", TOYFLAG_USR|TOYFLAG_BIN))
 USE_GETOPT(NEWTOY(getopt, "^a(alternative)n:(name)o:(options)l*(long)(longoptions)Tu", TOYFLAG_USR|TOYFLAG_BIN))
 USE_GETTY(NEWTOY(getty, "<2t#<0H:I:l:f:iwnmLh", TOYFLAG_SBIN))
+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_GPIOINFO(NEWTOY(gpiofind, "<1>1", TOYFLAG_USR|TOYFLAG_BIN))
+USE_GPIOFIND(NEWTOY(gpiofind, "<1>1", TOYFLAG_USR|TOYFLAG_BIN))
 USE_GPIOGET(NEWTOY(gpioget, "<2l", TOYFLAG_USR|TOYFLAG_BIN))
-USE_GPIOFIND(NEWTOY(gpioinfo, 0, TOYFLAG_USR|TOYFLAG_BIN))
+USE_GPIOINFO(NEWTOY(gpioinfo, 0, TOYFLAG_USR|TOYFLAG_BIN))
 USE_GPIOSET(NEWTOY(gpioset, "<2l", 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)rRsvwcL(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_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_GROUPADD(NEWTOY(groupadd, "<1>2g#<0S", TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
 USE_GROUPDEL(NEWTOY(groupdel, "<1>2", TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
 USE_GROUPS(NEWTOY(groups, NULL, TOYFLAG_USR|TOYFLAG_BIN))
-USE_GUNZIP(NEWTOY(gunzip, "cdfk123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_GZIP(NEWTOY(gzip,    "ncdfk123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_GUNZIP(NEWTOY(gunzip, "cdfkt123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
+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))
@@ -124,18 +129,19 @@
 USE_HOST(NEWTOY(host, "<1>2avt:", TOYFLAG_USR|TOYFLAG_BIN))
 USE_HOSTID(NEWTOY(hostid, ">0", TOYFLAG_USR|TOYFLAG_BIN))
 USE_HOSTNAME(NEWTOY(hostname, ">1bdsfF:[!bdsf]", TOYFLAG_BIN))
+USE_HTTPD(NEWTOY(httpd, ">1v", TOYFLAG_USR|TOYFLAG_BIN))
 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_I2CDETECT(NEWTOY(i2cdetect, ">3aFlqry[!qr]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_I2CDUMP(NEWTOY(i2cdump, "<2>2fy", TOYFLAG_USR|TOYFLAG_BIN))
-USE_I2CGET(NEWTOY(i2cget, "<3>3fy", TOYFLAG_USR|TOYFLAG_BIN))
-USE_I2CSET(NEWTOY(i2cset, "<4fy", TOYFLAG_USR|TOYFLAG_BIN))
+USE_I2CDETECT(NEWTOY(i2cdetect, ">3aFlqry[!qr]", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_I2CDUMP(NEWTOY(i2cdump, "<2>2fy", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_I2CGET(NEWTOY(i2cget, "<2>3fy", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_I2CSET(NEWTOY(i2cset, "<4fy", TOYFLAG_USR|TOYFLAG_SBIN))
 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_INSMOD(NEWTOY(insmod, "<1", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
-USE_INSTALL(NEWTOY(install, "<1cdDpsvt:m:o:g:", TOYFLAG_USR|TOYFLAG_BIN))
+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))
 USE_IORENICE(NEWTOY(iorenice, "<1>3", TOYFLAG_USR|TOYFLAG_BIN))
 USE_IOTOP(NEWTOY(iotop, ">0AaKO" "Hk*o*p*u*s#<1=7d%<100=3000m#n#<1bq", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT|TOYFLAG_LOCALE))
@@ -163,11 +169,11 @@
 USE_LOGNAME(NEWTOY(logname, ">0", TOYFLAG_USR|TOYFLAG_BIN))
 USE_LOGPATH(NEWTOY(logpath, 0, TOYFLAG_NOHELP|TOYFLAG_USR|TOYFLAG_BIN))
 USE_LOSETUP(NEWTOY(losetup, ">2S(sizelimit)#s(show)ro#j:fdcaD[!afj]", TOYFLAG_SBIN))
-USE_LS(NEWTOY(ls, "(color):;(full-time)(show-control-chars)ZgoACFHLRSabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][!qb]", TOYFLAG_BIN|TOYFLAG_LOCALE))
+USE_LS(NEWTOY(ls, "(sort):(color):;(full-time)(show-control-chars)\241(group-directories-first)\376ZgoACFHLNRSUXabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][-Nqb]", TOYFLAG_BIN|TOYFLAG_LOCALE))
 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@i:", 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_MAN(NEWTOY(man, "k:M:", TOYFLAG_USR|TOYFLAG_BIN))
@@ -186,19 +192,21 @@
 USE_MODINFO(NEWTOY(modinfo, "<1b:k:F:0", TOYFLAG_SBIN))
 USE_MODPROBE(NEWTOY(modprobe, "alrqvsDbd*", TOYFLAG_SBIN))
 USE_MORE(NEWTOY(more, 0, TOYFLAG_USR|TOYFLAG_BIN))
-USE_MOUNT(NEWTOY(mount, "?O:afnrvwt:o*[-rw]", TOYFLAG_BIN|TOYFLAG_STAYROOT))
+USE_MOUNT(NEWTOY(mount, "?RO:afnrvwt:o*[-rw]", TOYFLAG_BIN|TOYFLAG_STAYROOT))
 USE_MOUNTPOINT(NEWTOY(mountpoint, "<1qdx[-dx]", TOYFLAG_BIN))
-USE_MV(NEWTOY(mv, "<1vnF(remove-destination)fit:T[-ni]", TOYFLAG_BIN))
+USE_MV(NEWTOY(mv, "<1v(verbose)nF(remove-destination)fit:T[-ni]", TOYFLAG_BIN))
 USE_NBD_CLIENT(OLDTOY(nbd-client, nbd_client, TOYFLAG_USR|TOYFLAG_BIN))
-USE_NBD_CLIENT(NEWTOY(nbd_client, "<3>3ns", 0))
+USE_NBD_SERVER(OLDTOY(nbd-server, nbd_server, TOYFLAG_USR|TOYFLAG_BIN))
+USE_NBD_CLIENT(NEWTOY(nbd_client, "<3>3b#<1>4294967295=4096ns", 0))
+USE_NBD_SERVER(NEWTOY(nbd_server, "<1>1r", 0))
 USE_NETCAT(OLDTOY(nc, netcat, TOYFLAG_USR|TOYFLAG_BIN))
-USE_NETCAT(NEWTOY(netcat, USE_NETCAT_LISTEN("^tElL")"w#<1W#<1p#<1>65535q#<1s:f:46uU"USE_NETCAT_LISTEN("[!tlL][!Lw]")"[!46U]", TOYFLAG_BIN))
+USE_NETCAT(NEWTOY(netcat, "^tElLw#<1W#<1p#<1>65535q#<1s:f:46uUn[!tlL][!Lw][!Lu][!46U]", TOYFLAG_BIN))
 USE_NETSTAT(NEWTOY(netstat, "pWrxwutneal", TOYFLAG_BIN))
 USE_NICE(NEWTOY(nice, "^<1n#", TOYFLAG_BIN))
 USE_NL(NEWTOY(nl, "v#=1l#w#<0=6b:n:s:E", TOYFLAG_USR|TOYFLAG_BIN))
 USE_NOHUP(NEWTOY(nohup, "<1^", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(125)))
 USE_NPROC(NEWTOY(nproc, "(all)", TOYFLAG_USR|TOYFLAG_BIN))
-USE_NSENTER(NEWTOY(nsenter, "<1F(no-fork)t#<1(target)i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user);", TOYFLAG_USR|TOYFLAG_BIN))
+USE_NSENTER(NEWTOY(nsenter, "<1a(all)F(no-fork)t#<1(target)C(cgroup):; i(ipc):; m(mount):; n(net):; p(pid):; u(uts):; U(user):; ", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
 USE_OD(NEWTOY(od, "j#vw#<1=16N#xsodcbA:t*", TOYFLAG_USR|TOYFLAG_BIN))
 USE_ONEIT(NEWTOY(oneit, "^<1nc:p3[!pn]", TOYFLAG_SBIN))
 USE_OPENVT(NEWTOY(openvt, "^<1c#<1>63sw", TOYFLAG_BIN|TOYFLAG_NEEDROOT))
@@ -223,21 +231,21 @@
 USE_PWGEN(NEWTOY(pwgen, ">2r(remove):c(capitalize)n(numerals)y(symbols)s(secure)B(ambiguous)h(help)C1vA(no-capitalize)0(no-numerals)[-cA][-n0][-C1]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_READAHEAD(NEWTOY(readahead, NULL, TOYFLAG_BIN))
 USE_READELF(NEWTOY(readelf, "<1(dyn-syms)adehlnp:SsWx:", TOYFLAG_USR|TOYFLAG_BIN))
-USE_READLINK(NEWTOY(readlink, "<1nqmef(canonicalize)[-mef]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_REALPATH(OLDTOY(realpath, readlink, TOYFLAG_USR|TOYFLAG_BIN))
+USE_READLINK(NEWTOY(readlink, "<1vnf(canonicalize)emqz[-mef][-qv]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_REALPATH(NEWTOY(realpath, "<1(relative-base):R(relative-to):s(no-symlinks)LPemqz[-Ps][-LP][-me]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_REBOOT(NEWTOY(reboot, "d:fn", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
 USE_RENICE(NEWTOY(renice, "<1gpun#|", TOYFLAG_USR|TOYFLAG_BIN))
 USE_RESET(NEWTOY(reset, 0, TOYFLAG_USR|TOYFLAG_BIN))
 USE_RESTORECON(NEWTOY(restorecon, "<1DFnRrv", TOYFLAG_USR|TOYFLAG_SBIN))
 USE_REV(NEWTOY(rev, NULL, TOYFLAG_USR|TOYFLAG_BIN))
 USE_RFKILL(NEWTOY(rfkill, "<1>2", TOYFLAG_USR|TOYFLAG_SBIN))
-USE_RM(NEWTOY(rm, "fiRrv[-fi]", 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_ROUTE(NEWTOY(route, "?neA:", TOYFLAG_SBIN))
 USE_RTCWAKE(NEWTOY(rtcwake, "(list-modes);(auto)a(device)d:(local)l(mode)m:(seconds)s#(time)t#(utc)u(verbose)v[!alu]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_RUNCON(NEWTOY(runcon, "<2", TOYFLAG_USR|TOYFLAG_SBIN))
-USE_SED(NEWTOY(sed, "(help)(version)e*f*i:;nErz(null-data)s[+Er]", TOYFLAG_BIN|TOYFLAG_LOCALE|TOYFLAG_NOHELP))
+USE_RUNCON(NEWTOY(runcon, "^<2", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_SED(NEWTOY(sed, "(help)(version)(tarxform)e*f*i:;nErz(null-data)s[+Er]", TOYFLAG_BIN|TOYFLAG_LOCALE|TOYFLAG_NOHELP))
 USE_SENDEVENT(NEWTOY(sendevent, "<4>4", TOYFLAG_USR|TOYFLAG_SBIN))
 USE_SEQ(NEWTOY(seq, "<1>3?f:s:w[!fw]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_SH(NEWTOY(set, 0, TOYFLAG_NOFORK))
@@ -253,11 +261,12 @@
 USE_SHA512SUM(OLDTOY(sha512sum, md5sum, TOYFLAG_USR|TOYFLAG_BIN))
 USE_SH(NEWTOY(shift, ">1", TOYFLAG_NOFORK))
 USE_SHRED(NEWTOY(shred, "<1zxus#<1n#<1o#<0f", TOYFLAG_USR|TOYFLAG_BIN))
-USE_SKELETON(NEWTOY(skeleton, "(walrus)(blubber):;(also):e@d*c#b:a", TOYFLAG_USR|TOYFLAG_BIN))
+USE_SHUF(NEWTOY(shuf, "zen#<0", TOYFLAG_USR|TOYFLAG_BIN))
+USE_SKELETON(NEWTOY(skeleton, "(walrus)(blubber):;(also):h(hlong):; g(glong): f(longf):;e@d*c#b:a", TOYFLAG_USR|TOYFLAG_BIN))
 USE_SKELETON_ALIAS(NEWTOY(skeleton_alias, "b#dq", TOYFLAG_USR|TOYFLAG_BIN))
 USE_SLEEP(NEWTOY(sleep, "<1", TOYFLAG_BIN))
 USE_SNTP(NEWTOY(sntp, ">1M :m :Sp:t#<0=1>16asdDqr#<4>17=10[!as]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_SORT(NEWTOY(sort, USE_SORT_FLOAT("g")"S:T:m" "o:k*t:" "xVbMcszdfirun", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
+USE_SORT(NEWTOY(sort, USE_SORT_FLOAT("g")"S:T:m" "o:k*t:" "xVbMCcszdfirun", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
 USE_SH(NEWTOY(source, "<1", TOYFLAG_NOFORK))
 USE_SPLIT(NEWTOY(split, ">2a#<1=2>9b#<1l#<1n#<1[!bl][!bn][!ln]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_STAT(NEWTOY(stat, "<1c:(format)fLt", TOYFLAG_BIN))
@@ -266,7 +275,7 @@
 USE_STTY(NEWTOY(stty, "?aF:g[!ag]", TOYFLAG_BIN))
 USE_SU(NEWTOY(su, "^lmpu:g:c:s:[!lmp]", TOYFLAG_BIN|TOYFLAG_ROOTONLY))
 USE_SULOGIN(NEWTOY(sulogin, "t#<0=0", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
-USE_SWAPOFF(NEWTOY(swapoff, "<1>1", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
+USE_SWAPOFF(NEWTOY(swapoff, "<1>1av", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
 USE_SWAPON(NEWTOY(swapon, "<1>1p#<0>32767d", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
 USE_SWITCH_ROOT(NEWTOY(switch_root, "<2c:h", TOYFLAG_SBIN))
 USE_SYNC(NEWTOY(sync, NULL, TOYFLAG_BIN))
@@ -274,9 +283,9 @@
 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_TAC(NEWTOY(tac, NULL, TOYFLAG_USR|TOYFLAG_BIN))
 USE_TAIL(NEWTOY(tail, "?fFs:c(bytes)-n(lines)-[-cn][-fF]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_TAR(NEWTOY(tar, "&(strip-components)#(selinux)(restrict)(full-time)(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mode):(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)I(use-compress-program):J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):a[!txc][!jzJa]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_TASKSET(NEWTOY(taskset, "<1^pa", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
-USE_TCPSVD(NEWTOY(tcpsvd, "^<3c#=30<1C:b#=20<0u:l:hEv", TOYFLAG_USR|TOYFLAG_BIN))
+USE_TAR(NEWTOY(tar, "&(no-ignore-case)(ignore-case)(no-anchored)(anchored)(no-wildcards)(wildcards)(no-wildcards-match-slash)(wildcards-match-slash)(show-transformed-names)(selinux)(restrict)(full-time)(no-recursion)(null)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(sort);:(mode):(mtime):(group):(owner):(to-command):~(strip-components)(strip)#~(transform)(xform)*o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*I(use-compress-program):C(directory):f(file):as[!txc][!jzJa]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_TASKSET(NEWTOY(taskset, "<1^pa", TOYFLAG_USR|TOYFLAG_BIN))
+USE_TCPSVD(NEWTOY(tcpsvd, "^<3c#=30<1b#=20<0C:u:l:hEv", 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))
@@ -284,7 +293,7 @@
 USE_TFTP(NEWTOY(tftp, "<1b#<8>65464r:l:g|p|[!gp]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_TFTPD(NEWTOY(tftpd, "rcu:l", TOYFLAG_BIN))
 USE_TIME(NEWTOY(time, "<1^pv[-pv]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_MAYFORK))
-USE_TIMEOUT(NEWTOY(timeout, "<2^(foreground)(preserve-status)vk:s(signal):", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(125)))
+USE_TIMEOUT(NEWTOY(timeout, "<2^(foreground)(preserve-status)vk:s(signal):i", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(125)))
 USE_TOP(NEWTOY(top, ">0O*h" "Hk*o*p*u*s#<1d%<100=3000m#n#<1bq[!oO]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
 USE_TOUCH(NEWTOY(touch, "<1acd:fmr:t:h[!dtr]", TOYFLAG_BIN))
 USE_SH(OLDTOY(toysh, sh, TOYFLAG_BIN))
@@ -299,17 +308,17 @@
 USE_TCPSVD(OLDTOY(udpsvd, tcpsvd, TOYFLAG_USR|TOYFLAG_BIN))
 USE_ULIMIT(NEWTOY(ulimit, ">1P#<1SHavutsrRqpnmlifedc[-SH][!apvutsrRqnmlifedc]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_UMOUNT(NEWTOY(umount, "cndDflrat*v[!na]", TOYFLAG_BIN|TOYFLAG_STAYROOT))
-USE_UNAME(NEWTOY(uname, "aomvrns", TOYFLAG_BIN))
+USE_UNAME(NEWTOY(uname, "paomvrns", TOYFLAG_BIN))
 USE_UNICODE(NEWTOY(unicode, "<1", TOYFLAG_USR|TOYFLAG_BIN))
 USE_UNIQ(NEWTOY(uniq, "f#s#w#zicdu", TOYFLAG_USR|TOYFLAG_BIN))
 USE_UNIX2DOS(NEWTOY(unix2dos, 0, TOYFLAG_BIN))
 USE_UNLINK(NEWTOY(unlink, "<1>1", TOYFLAG_USR|TOYFLAG_BIN))
 USE_SH(NEWTOY(unset, "fvn[!fv]", TOYFLAG_NOFORK))
-USE_UNSHARE(NEWTOY(unshare, "<1^f(fork);r(map-root-user);i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user);", TOYFLAG_USR|TOYFLAG_BIN))
+USE_UNSHARE(NEWTOY(unshare, "<1^a(all)f(fork)r(map-root-user)C(cgroup):; i(ipc):; m(mount):; n(net):; p(pid):; u(uts):; U(user):; ", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
 USE_UPTIME(NEWTOY(uptime, ">0ps", TOYFLAG_USR|TOYFLAG_BIN))
 USE_USERADD(NEWTOY(useradd, "<1>2u#<0G:s:g:h:SDH", TOYFLAG_NEEDROOT|TOYFLAG_UMASK|TOYFLAG_SBIN))
 USE_USERDEL(NEWTOY(userdel, "<1>1r", TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
-USE_USLEEP(NEWTOY(usleep, "<1", TOYFLAG_BIN))
+USE_USLEEP(NEWTOY(usleep, "<1>1", TOYFLAG_BIN))
 USE_UUDECODE(NEWTOY(uudecode, ">1o:", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_UMASK))
 USE_UUENCODE(NEWTOY(uuencode, "<1>2m", TOYFLAG_USR|TOYFLAG_BIN))
 USE_UUIDGEN(NEWTOY(uuidgen, ">0r(random)", TOYFLAG_USR|TOYFLAG_BIN))
@@ -319,14 +328,14 @@
 USE_W(NEWTOY(w, NULL, TOYFLAG_USR|TOYFLAG_BIN))
 USE_SH(NEWTOY(wait, "n", TOYFLAG_NOFORK))
 USE_WATCH(NEWTOY(watch, "^<1n%<100=2000tebx", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
-USE_WATCHDOG(NEWTOY(watchdog, "<1>1Ft#=4<1T#=60<1", TOYFLAG_NEEDROOT|TOYFLAG_BIN))
+USE_WATCHDOG(NEWTOY(watchdog, "<1>1Ft#=4<1T#=60<1", TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
 USE_WC(NEWTOY(wc, "mcwl", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
 USE_WGET(NEWTOY(wget, "<1>1(max-redirect)#<0=20d(debug)O(output-document):p(post-data):", TOYFLAG_USR|TOYFLAG_BIN))
 USE_WHICH(NEWTOY(which, "<1a", TOYFLAG_USR|TOYFLAG_BIN))
 USE_WHO(NEWTOY(who, "a", TOYFLAG_USR|TOYFLAG_BIN))
 USE_WHOAMI(OLDTOY(whoami, logname, TOYFLAG_USR|TOYFLAG_BIN))
-USE_XARGS(NEWTOY(xargs, "^E:P#<0=1optrn#<1(max-args)s#0[!0E]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_XXD(NEWTOY(xxd, ">1c#<0>256l#o#g#<1=2iprs#[!rs]", 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_XXD(NEWTOY(xxd, ">1c#<0>256l#o#g#<0=2eiprs#[!rs][!re]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_XZCAT(NEWTOY(xzcat, NULL, TOYFLAG_USR|TOYFLAG_BIN))
 USE_YES(NEWTOY(yes, NULL, TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
-USE_ZCAT(NEWTOY(zcat,     "cdfk123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_ZCAT(NEWTOY(zcat,     "cdfkt123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
diff --git a/android/linux/generated/config.h b/android/linux/generated/config.h
index 7d2c730..a1d03da 100644
--- a/android/linux/generated/config.h
+++ b/android/linux/generated/config.h
@@ -1,61 +1,35 @@
-#define CFG_TOYBOX_ANDROID_SCHEDPOLICY 0
-#define USE_TOYBOX_ANDROID_SCHEDPOLICY(...)
-#define CFG_TOYBOX_CONTAINER 0
-#define USE_TOYBOX_CONTAINER(...)
-#define CFG_TOYBOX_COPYFILERANGE 0
-#define USE_TOYBOX_COPYFILERANGE(...)
+#define CFG_TOYBOX 1
+#define USE_TOYBOX(...) __VA_ARGS__
 #define CFG_TOYBOX_DEBUG 0
 #define USE_TOYBOX_DEBUG(...)
-#define CFG_TOYBOX_FALLOCATE 0
-#define USE_TOYBOX_FALLOCATE(...)
-#define CFG_TOYBOX_FIFREEZE 0
-#define USE_TOYBOX_FIFREEZE(...)
 #define CFG_TOYBOX_FLOAT 1
 #define USE_TOYBOX_FLOAT(...) __VA_ARGS__
 #define CFG_TOYBOX_FORK 1
 #define USE_TOYBOX_FORK(...) __VA_ARGS__
 #define CFG_TOYBOX_FREE 0
 #define USE_TOYBOX_FREE(...)
-#define CFG_TOYBOX_GETRANDOM 0
-#define USE_TOYBOX_GETRANDOM(...)
 #define CFG_TOYBOX_HELP_DASHDASH 1
 #define USE_TOYBOX_HELP_DASHDASH(...) __VA_ARGS__
 #define CFG_TOYBOX_HELP 1
 #define USE_TOYBOX_HELP(...) __VA_ARGS__
-#define CFG_TOYBOX_I18N 1
-#define USE_TOYBOX_I18N(...) __VA_ARGS__
-#define CFG_TOYBOX_ICONV 1
-#define USE_TOYBOX_ICONV(...) __VA_ARGS__
 #define CFG_TOYBOX_LIBCRYPTO 1
 #define USE_TOYBOX_LIBCRYPTO(...) __VA_ARGS__
 #define CFG_TOYBOX_LIBZ 1
 #define USE_TOYBOX_LIBZ(...) __VA_ARGS__
 #define CFG_TOYBOX_LSM_NONE 1
 #define USE_TOYBOX_LSM_NONE(...) __VA_ARGS__
-#define CFG_TOYBOX_MUSL_NOMMU_IS_BROKEN 0
-#define USE_TOYBOX_MUSL_NOMMU_IS_BROKEN(...)
-#define CFG_TOYBOX_NORECURSE 0
-#define USE_TOYBOX_NORECURSE(...)
+#define CFG_TOYBOX_NORECURSE 1
+#define USE_TOYBOX_NORECURSE(...) __VA_ARGS__
 #define CFG_TOYBOX_ON_ANDROID 0
 #define USE_TOYBOX_ON_ANDROID(...)
-#define CFG_TOYBOX_PEDANTIC_ARGS 0
-#define USE_TOYBOX_PEDANTIC_ARGS(...)
-#define CFG_TOYBOX_PRLIMIT 0
-#define USE_TOYBOX_PRLIMIT(...)
 #define CFG_TOYBOX_SELINUX 0
 #define USE_TOYBOX_SELINUX(...)
-#define CFG_TOYBOX_SHADOW 0
-#define USE_TOYBOX_SHADOW(...)
 #define CFG_TOYBOX_SMACK 0
 #define USE_TOYBOX_SMACK(...)
-#define CFG_TOYBOX_SUID 1
-#define USE_TOYBOX_SUID(...) __VA_ARGS__
+#define CFG_TOYBOX_SUID 0
+#define USE_TOYBOX_SUID(...)
 #define CFG_TOYBOX_UID_SYS 100
 #define CFG_TOYBOX_UID_USR 500
-#define CFG_TOYBOX_UTMPX 0
-#define USE_TOYBOX_UTMPX(...)
-#define CFG_TOYBOX 1
-#define USE_TOYBOX(...) __VA_ARGS__
 #define CFG_ACPI 0
 #define USE_ACPI(...)
 #define CFG_ARCH 0
@@ -90,10 +64,6 @@
 #define USE_BZCAT(...)
 #define CFG_CAL 0
 #define USE_CAL(...)
-#define CFG_CATV 0
-#define USE_CATV(...)
-#define CFG_CAT_V 1
-#define USE_CAT_V(...) __VA_ARGS__
 #define CFG_CAT 1
 #define USE_CAT(...) __VA_ARGS__
 #define CFG_CD 0
@@ -128,8 +98,6 @@
 #define USE_COUNT(...)
 #define CFG_CPIO 1
 #define USE_CPIO(...) __VA_ARGS__
-#define CFG_CP_PRESERVE 1
-#define USE_CP_PRESERVE(...) __VA_ARGS__
 #define CFG_CP 1
 #define USE_CP(...) __VA_ARGS__
 #define CFG_CRC32 0
@@ -204,8 +172,8 @@
 #define USE_FDISK(...)
 #define CFG_FGREP 1
 #define USE_FGREP(...) __VA_ARGS__
-#define CFG_FILE 0
-#define USE_FILE(...)
+#define CFG_FILE 1
+#define USE_FILE(...) __VA_ARGS__
 #define CFG_FIND 1
 #define USE_FIND(...) __VA_ARGS__
 #define CFG_FLOCK 0
@@ -240,6 +208,18 @@
 #define USE_GETOPT(...) __VA_ARGS__
 #define CFG_GETTY 0
 #define USE_GETTY(...)
+#define CFG_GITCHECKOUT 0
+#define USE_GITCHECKOUT(...)
+#define CFG_GITCLONE 0
+#define USE_GITCLONE(...)
+#define CFG_GITCOMPAT 0
+#define USE_GITCOMPAT(...)
+#define CFG_GITFETCH 0
+#define USE_GITFETCH(...)
+#define CFG_GITINIT 0
+#define USE_GITINIT(...)
+#define CFG_GITREMOTE 0
+#define USE_GITREMOTE(...)
 #define CFG_GPIODETECT 0
 #define USE_GPIODETECT(...)
 #define CFG_GPIOFIND 0
@@ -266,8 +246,6 @@
 #define USE_HEAD(...) __VA_ARGS__
 #define CFG_HELLO 0
 #define USE_HELLO(...)
-#define CFG_HELP_EXTRAS 0
-#define USE_HELP_EXTRAS(...)
 #define CFG_HELP 0
 #define USE_HELP(...)
 #define CFG_HEXDUMP 0
@@ -282,6 +260,8 @@
 #define USE_HOST(...)
 #define CFG_HOSTNAME 1
 #define USE_HOSTNAME(...) __VA_ARGS__
+#define CFG_HTTPD 0
+#define USE_HTTPD(...)
 #define CFG_HWCLOCK 0
 #define USE_HWCLOCK(...)
 #define CFG_I2CDETECT 0
@@ -350,8 +330,6 @@
 #define USE_LOGNAME(...)
 #define CFG_LOGPATH 0
 #define USE_LOGPATH(...)
-#define CFG_LOGWRAPPER 0
-#define USE_LOGWRAPPER(...)
 #define CFG_LOSETUP 0
 #define USE_LOSETUP(...)
 #define CFG_LSATTR 0
@@ -362,8 +340,6 @@
 #define USE_LSOF(...)
 #define CFG_LSPCI 0
 #define USE_LSPCI(...)
-#define CFG_LSPCI_TEXT 0
-#define USE_LSPCI_TEXT(...)
 #define CFG_LSUSB 0
 #define USE_LSUSB(...)
 #define CFG_LS 1
@@ -426,10 +402,10 @@
 #define USE_MV(...) __VA_ARGS__
 #define CFG_NBD_CLIENT 0
 #define USE_NBD_CLIENT(...)
+#define CFG_NBD_SERVER 0
+#define USE_NBD_SERVER(...)
 #define CFG_NETCAT 0
 #define USE_NETCAT(...)
-#define CFG_NETCAT_LISTEN 0
-#define USE_NETCAT_LISTEN(...)
 #define CFG_NETSTAT 0
 #define USE_NETSTAT(...)
 #define CFG_NICE 0
@@ -542,6 +518,8 @@
 #define USE_SH(...)
 #define CFG_SHRED 0
 #define USE_SHRED(...)
+#define CFG_SHUF 0
+#define USE_SHUF(...)
 #define CFG_SKELETON_ALIAS 0
 #define USE_SKELETON_ALIAS(...)
 #define CFG_SKELETON 0
@@ -678,8 +656,6 @@
 #define USE_WHO(...)
 #define CFG_W 0
 #define USE_W(...)
-#define CFG_XARGS_PEDANTIC 0
-#define USE_XARGS_PEDANTIC(...)
 #define CFG_XARGS 1
 #define USE_XARGS(...) __VA_ARGS__
 #define CFG_XXD 1
diff --git a/android/linux/generated/flags.h b/android/linux/generated/flags.h
index 2ab033b..3e550a7 100644
--- a/android/linux/generated/flags.h
+++ b/android/linux/generated/flags.h
@@ -1,11 +1,8 @@
 #undef FORCED_FLAG
-#undef FORCED_FLAGLL
 #ifdef FORCE_FLAGS
-#define FORCED_FLAG 1
-#define FORCED_FLAGLL 1ULL
+#define FORCED_FLAG 1LL
 #else
-#define FORCED_FLAG 0
-#define FORCED_FLAGLL 0LL
+#define FORCED_FLAG 0LL
 #endif
 
 // acpi   abctV
@@ -131,13 +128,14 @@
 #undef FLAG_f
 #endif
 
-// blkid   ULs*[!LU]
+// blkid   ULo:s*[!LU]
 #undef OPTSTR_blkid
-#define OPTSTR_blkid "ULs*[!LU]"
+#define OPTSTR_blkid "ULo:s*[!LU]"
 #ifdef CLEANUP_blkid
 #undef CLEANUP_blkid
 #undef FOR_blkid
 #undef FLAG_s
+#undef FLAG_o
 #undef FLAG_L
 #undef FLAG_U
 #endif
@@ -221,17 +219,6 @@
 #undef FLAG_u
 #endif
 
-// catv   vte
-#undef OPTSTR_catv
-#define OPTSTR_catv "vte"
-#ifdef CLEANUP_catv
-#undef CLEANUP_catv
-#undef FOR_catv
-#undef FLAG_e
-#undef FLAG_t
-#undef FLAG_v
-#endif
-
 // cd   >1LP[-LP]
 #undef OPTSTR_cd
 #define OPTSTR_cd ">1LP[-LP]"
@@ -323,9 +310,9 @@
 #undef FLAG_s
 #endif
 
-// chvt   <1
+// chvt   <1>1
 #undef OPTSTR_chvt
-#define OPTSTR_chvt "<1"
+#define OPTSTR_chvt "<1>1"
 #ifdef CLEANUP_chvt
 #undef CLEANUP_chvt
 #undef FOR_chvt
@@ -410,9 +397,9 @@
 #undef FLAG_preserve
 #endif
 
-// cpio (ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF] (ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]
+// cpio (ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)R(owner):md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF] (ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)R(owner):md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]
 #undef OPTSTR_cpio
-#define OPTSTR_cpio "(ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]"
+#define OPTSTR_cpio "(ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)R(owner):md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]"
 #ifdef CLEANUP_cpio
 #undef CLEANUP_cpio
 #undef FOR_cpio
@@ -426,6 +413,7 @@
 #undef FLAG_u
 #undef FLAG_d
 #undef FLAG_m
+#undef FLAG_R
 #undef FLAG_no_preserve_owner
 #undef FLAG_quiet
 #undef FLAG_renumber_inodes
@@ -468,9 +456,9 @@
 #undef FLAG_c
 #endif
 
-// cut b*|c*|f*|F*|C*|O(output-delimiter):d:sDn[!cbfF] b*|c*|f*|F*|C*|O(output-delimiter):d:sDn[!cbfF]
+// cut b*|c*|f*|F(regex-fields)*|C*|O(output-delimiter):d:sD(allow-duplicates)n[!cbfF] b*|c*|f*|F(regex-fields)*|C*|O(output-delimiter):d:sD(allow-duplicates)n[!cbfF]
 #undef OPTSTR_cut
-#define OPTSTR_cut "b*|c*|f*|F*|C*|O(output-delimiter):d:sDn[!cbfF]"
+#define OPTSTR_cut "b*|c*|f*|F(regex-fields)*|C*|O(output-delimiter):d:sD(allow-duplicates)n[!cbfF]"
 #ifdef CLEANUP_cut
 #undef CLEANUP_cut
 #undef FOR_cut
@@ -486,9 +474,9 @@
 #undef FLAG_b
 #endif
 
-// date d:D:I(iso)(iso-8601):;r:s:u(utc)[!dr] d:D:I(iso)(iso-8601):;r:s:u(utc)[!dr]
+// date d:D:I(iso-8601):;r:s:u(utc)[!dr] d:D:I(iso-8601):;r:s:u(utc)[!dr]
 #undef OPTSTR_date
-#define OPTSTR_date "d:D:I(iso)(iso-8601):;r:s:u(utc)[!dr]"
+#define OPTSTR_date "d:D:I(iso-8601):;r:s:u(utc)[!dr]"
 #ifdef CLEANUP_date
 #undef CLEANUP_date
 #undef FOR_date
@@ -714,17 +702,18 @@
 #undef FLAG_P
 #endif
 
-// diff <2>2(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)L(label)*S(starting-file):N(new-file)r(recursive)U(unified)#<0=3 <2>2(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)L(label)*S(starting-file):N(new-file)r(recursive)U(unified)#<0=3
+// diff <2>2(unchanged-line-format):;(old-line-format):;(new-line-format):;(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)S(starting-file):F(show-function-line):;L(label)*N(new-file)r(recursive)U(unified)#<0=3 <2>2(unchanged-line-format):;(old-line-format):;(new-line-format):;(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)S(starting-file):F(show-function-line):;L(label)*N(new-file)r(recursive)U(unified)#<0=3
 #undef OPTSTR_diff
-#define OPTSTR_diff "<2>2(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)L(label)*S(starting-file):N(new-file)r(recursive)U(unified)#<0=3"
+#define OPTSTR_diff "<2>2(unchanged-line-format):;(old-line-format):;(new-line-format):;(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)S(starting-file):F(show-function-line):;L(label)*N(new-file)r(recursive)U(unified)#<0=3"
 #ifdef CLEANUP_diff
 #undef CLEANUP_diff
 #undef FOR_diff
 #undef FLAG_U
 #undef FLAG_r
 #undef FLAG_N
-#undef FLAG_S
 #undef FLAG_L
+#undef FLAG_F
+#undef FLAG_S
 #undef FLAG_a
 #undef FLAG_q
 #undef FLAG_s
@@ -738,6 +727,9 @@
 #undef FLAG_B
 #undef FLAG_strip_trailing_cr
 #undef FLAG_color
+#undef FLAG_new_line_format
+#undef FLAG_old_line_format
+#undef FLAG_unchanged_line_format
 #endif
 
 // dirname <1 <1
@@ -900,12 +892,14 @@
 #undef FOR_expr
 #endif
 
-// factor    
+// factor   ?hx
 #undef OPTSTR_factor
-#define OPTSTR_factor 0
+#define OPTSTR_factor "?hx"
 #ifdef CLEANUP_factor
 #undef CLEANUP_factor
 #undef FOR_factor
+#undef FLAG_x
+#undef FLAG_h
 #endif
 
 // fallocate   >1l#|o#
@@ -940,9 +934,9 @@
 #undef FLAG_C
 #endif
 
-// file   <1bhLs[!hL]
+// file <1b(brief)hLs[!hL] <1b(brief)hLs[!hL]
 #undef OPTSTR_file
-#define OPTSTR_file "<1bhLs[!hL]"
+#define OPTSTR_file "<1b(brief)hLs[!hL]"
 #ifdef CLEANUP_file
 #undef CLEANUP_file
 #undef FOR_file
@@ -1144,6 +1138,46 @@
 #undef FLAG_t
 #endif
 
+// gitcheckout   <1
+#undef OPTSTR_gitcheckout
+#define OPTSTR_gitcheckout "<1"
+#ifdef CLEANUP_gitcheckout
+#undef CLEANUP_gitcheckout
+#undef FOR_gitcheckout
+#endif
+
+// gitclone   <1
+#undef OPTSTR_gitclone
+#define OPTSTR_gitclone "<1"
+#ifdef CLEANUP_gitclone
+#undef CLEANUP_gitclone
+#undef FOR_gitclone
+#endif
+
+// gitfetch    
+#undef OPTSTR_gitfetch
+#define OPTSTR_gitfetch 0
+#ifdef CLEANUP_gitfetch
+#undef CLEANUP_gitfetch
+#undef FOR_gitfetch
+#endif
+
+// gitinit   <1
+#undef OPTSTR_gitinit
+#define OPTSTR_gitinit "<1"
+#ifdef CLEANUP_gitinit
+#undef CLEANUP_gitinit
+#undef FOR_gitinit
+#endif
+
+// gitremote   <1
+#undef OPTSTR_gitremote
+#define OPTSTR_gitremote "<1"
+#ifdef CLEANUP_gitremote
+#undef CLEANUP_gitremote
+#undef FOR_gitremote
+#endif
+
 // gpiodetect   >0
 #undef OPTSTR_gpiodetect
 #define OPTSTR_gpiodetect ">0"
@@ -1186,9 +1220,9 @@
 #undef FLAG_l
 #endif
 
-// grep (line-buffered)(color):;(exclude-dir)*S(exclude)*M(include)*ZzEFHIab(byte-offset)h(no-filename)ino(only-matching)rRsvwcL(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)rRsvwcL(files-without-match)l(files-with-matches)q(quiet)(silent)e*f*C#B#A#m#x[!wx][!EF]
+// 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)rRsvwcL(files-without-match)l(files-with-matches)q(quiet)(silent)e*f*C#B#A#m#x[!wx][!EF]"
+#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
@@ -1253,9 +1287,9 @@
 #undef FOR_groups
 #endif
 
-// gunzip   cdfk123456789[-123456789]
+// gunzip   cdfkt123456789[-123456789]
 #undef OPTSTR_gunzip
-#define OPTSTR_gunzip "cdfk123456789[-123456789]"
+#define OPTSTR_gunzip "cdfkt123456789[-123456789]"
 #ifdef CLEANUP_gunzip
 #undef CLEANUP_gunzip
 #undef FOR_gunzip
@@ -1268,15 +1302,16 @@
 #undef FLAG_3
 #undef FLAG_2
 #undef FLAG_1
+#undef FLAG_t
 #undef FLAG_k
 #undef FLAG_f
 #undef FLAG_d
 #undef FLAG_c
 #endif
 
-// gzip ncdfk123456789[-123456789] ncdfk123456789[-123456789]
+// gzip n(no-name)cdfkt123456789[-123456789] n(no-name)cdfkt123456789[-123456789]
 #undef OPTSTR_gzip
-#define OPTSTR_gzip "ncdfk123456789[-123456789]"
+#define OPTSTR_gzip "n(no-name)cdfkt123456789[-123456789]"
 #ifdef CLEANUP_gzip
 #undef CLEANUP_gzip
 #undef FOR_gzip
@@ -1289,6 +1324,7 @@
 #undef FLAG_3
 #undef FLAG_2
 #undef FLAG_1
+#undef FLAG_t
 #undef FLAG_k
 #undef FLAG_f
 #undef FLAG_d
@@ -1385,6 +1421,15 @@
 #undef FLAG_b
 #endif
 
+// httpd   >1v
+#undef OPTSTR_httpd
+#define OPTSTR_httpd ">1v"
+#ifdef CLEANUP_httpd
+#undef CLEANUP_httpd
+#undef FOR_httpd
+#undef FLAG_v
+#endif
+
 // hwclock   >0(fast)f(rtc):u(utc)l(localtime)t(systz)s(hctosys)r(show)w(systohc)[-ul][!rtsw]
 #undef OPTSTR_hwclock
 #define OPTSTR_hwclock ">0(fast)f(rtc):u(utc)l(localtime)t(systz)s(hctosys)r(show)w(systohc)[-ul][!rtsw]"
@@ -1425,9 +1470,9 @@
 #undef FLAG_f
 #endif
 
-// i2cget   <3>3fy
+// i2cget   <2>3fy
 #undef OPTSTR_i2cget
-#define OPTSTR_i2cget "<3>3fy"
+#define OPTSTR_i2cget "<2>3fy"
 #ifdef CLEANUP_i2cget
 #undef CLEANUP_i2cget
 #undef FOR_i2cget
@@ -1505,9 +1550,9 @@
 #undef FOR_insmod
 #endif
 
-// install <1cdDpsvt:m:o:g: <1cdDpsvt:m:o:g:
+// install <1cdDp(preserve-timestamps)svt:m:o:g: <1cdDp(preserve-timestamps)svt:m:o:g:
 #undef OPTSTR_install
-#define OPTSTR_install "<1cdDpsvt:m:o:g:"
+#define OPTSTR_install "<1cdDp(preserve-timestamps)svt:m:o:g:"
 #ifdef CLEANUP_install
 #undef CLEANUP_install
 #undef FOR_install
@@ -1779,9 +1824,9 @@
 #undef FLAG_S
 #endif
 
-// ls (color):;(full-time)(show-control-chars)ZgoACFHLRSabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][!qb] (color):;(full-time)(show-control-chars)ZgoACFHLRSabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][!qb]
+// ls (sort):(color):;(full-time)(show-control-chars)¡(group-directories-first)þZgoACFHLNRSUXabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][-Nqb] (sort):(color):;(full-time)(show-control-chars)¡(group-directories-first)þZgoACFHLNRSUXabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][-Nqb]
 #undef OPTSTR_ls
-#define OPTSTR_ls "(color):;(full-time)(show-control-chars)ZgoACFHLRSabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][!qb]"
+#define OPTSTR_ls "(sort):(color):;(full-time)(show-control-chars)¡(group-directories-first)þZgoACFHLNRSUXabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][-Nqb]"
 #ifdef CLEANUP_ls
 #undef CLEANUP_ls
 #undef FOR_ls
@@ -1805,8 +1850,11 @@
 #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
@@ -1815,9 +1863,12 @@
 #undef FLAG_o
 #undef FLAG_g
 #undef FLAG_Z
+#undef FLAG_X7E
+#undef FLAG_X21
 #undef FLAG_show_control_chars
 #undef FLAG_full_time
 #undef FLAG_color
+#undef FLAG_sort
 #endif
 
 // lsattr   ldapvR
@@ -1853,13 +1904,14 @@
 #undef FLAG_l
 #endif
 
-// lspci   emkn@i:
+// lspci   emkn@x@i:
 #undef OPTSTR_lspci
-#define OPTSTR_lspci "emkn@i:"
+#define OPTSTR_lspci "emkn@x@i:"
 #ifdef CLEANUP_lspci
 #undef CLEANUP_lspci
 #undef FOR_lspci
 #undef FLAG_i
+#undef FLAG_x
 #undef FLAG_n
 #undef FLAG_k
 #undef FLAG_m
@@ -2065,9 +2117,9 @@
 #undef FOR_more
 #endif
 
-// mount   ?O:afnrvwt:o*[-rw]
+// mount   ?RO:afnrvwt:o*[-rw]
 #undef OPTSTR_mount
-#define OPTSTR_mount "?O:afnrvwt:o*[-rw]"
+#define OPTSTR_mount "?RO:afnrvwt:o*[-rw]"
 #ifdef CLEANUP_mount
 #undef CLEANUP_mount
 #undef FOR_mount
@@ -2080,6 +2132,7 @@
 #undef FLAG_f
 #undef FLAG_a
 #undef FLAG_O
+#undef FLAG_R
 #endif
 
 // mountpoint   <1qdx[-dx]
@@ -2093,9 +2146,9 @@
 #undef FLAG_q
 #endif
 
-// mv <1vnF(remove-destination)fit:T[-ni] <1vnF(remove-destination)fit:T[-ni]
+// mv <1v(verbose)nF(remove-destination)fit:T[-ni] <1v(verbose)nF(remove-destination)fit:T[-ni]
 #undef OPTSTR_mv
-#define OPTSTR_mv "<1vnF(remove-destination)fit:T[-ni]"
+#define OPTSTR_mv "<1v(verbose)nF(remove-destination)fit:T[-ni]"
 #ifdef CLEANUP_mv
 #undef CLEANUP_mv
 #undef FOR_mv
@@ -2108,22 +2161,33 @@
 #undef FLAG_v
 #endif
 
-// nbd_client   <3>3ns
+// nbd_client   <3>3b#<1>4294967295=4096ns
 #undef OPTSTR_nbd_client
-#define OPTSTR_nbd_client "<3>3ns"
+#define OPTSTR_nbd_client "<3>3b#<1>4294967295=4096ns"
 #ifdef CLEANUP_nbd_client
 #undef CLEANUP_nbd_client
 #undef FOR_nbd_client
 #undef FLAG_s
 #undef FLAG_n
+#undef FLAG_b
 #endif
 
-// netcat   ^tElLw#<1W#<1p#<1>65535q#<1s:f:46uU[!tlL][!Lw][!46U]
+// nbd_server   <1>1r
+#undef OPTSTR_nbd_server
+#define OPTSTR_nbd_server "<1>1r"
+#ifdef CLEANUP_nbd_server
+#undef CLEANUP_nbd_server
+#undef FOR_nbd_server
+#undef FLAG_r
+#endif
+
+// netcat   ^tElLw#<1W#<1p#<1>65535q#<1s:f:46uUn[!tlL][!Lw][!Lu][!46U]
 #undef OPTSTR_netcat
-#define OPTSTR_netcat "^tElLw#<1W#<1p#<1>65535q#<1s:f:46uU[!tlL][!Lw][!46U]"
+#define OPTSTR_netcat "^tElLw#<1W#<1p#<1>65535q#<1s:f:46uUn[!tlL][!Lw][!Lu][!46U]"
 #ifdef CLEANUP_netcat
 #undef CLEANUP_netcat
 #undef FOR_netcat
+#undef FLAG_n
 #undef FLAG_U
 #undef FLAG_u
 #undef FLAG_6
@@ -2200,9 +2264,9 @@
 #undef FLAG_all
 #endif
 
-// nsenter   <1F(no-fork)t#<1(target)i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user);
+// nsenter   <1a(all)F(no-fork)t#<1(target)C(cgroup):; i(ipc):; m(mount):; n(net):; p(pid):; u(uts):; U(user):; 
 #undef OPTSTR_nsenter
-#define OPTSTR_nsenter "<1F(no-fork)t#<1(target)i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user);"
+#define OPTSTR_nsenter "<1a(all)F(no-fork)t#<1(target)C(cgroup):; i(ipc):; m(mount):; n(net):; p(pid):; u(uts):; U(user):; "
 #ifdef CLEANUP_nsenter
 #undef CLEANUP_nsenter
 #undef FOR_nsenter
@@ -2212,8 +2276,10 @@
 #undef FLAG_n
 #undef FLAG_m
 #undef FLAG_i
+#undef FLAG_C
 #undef FLAG_t
 #undef FLAG_F
+#undef FLAG_a
 #endif
 
 // od j#vw#<1=16N#xsodcbA:t* j#vw#<1=16N#xsodcbA:t*
@@ -2521,17 +2587,36 @@
 #undef FLAG_dyn_syms
 #endif
 
-// readlink <1nqmef(canonicalize)[-mef] <1nqmef(canonicalize)[-mef]
+// readlink <1vnf(canonicalize)emqz[-mef][-qv] <1vnf(canonicalize)emqz[-mef][-qv]
 #undef OPTSTR_readlink
-#define OPTSTR_readlink "<1nqmef(canonicalize)[-mef]"
+#define OPTSTR_readlink "<1vnf(canonicalize)emqz[-mef][-qv]"
 #ifdef CLEANUP_readlink
 #undef CLEANUP_readlink
 #undef FOR_readlink
-#undef FLAG_f
-#undef FLAG_e
-#undef FLAG_m
+#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] <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
 
 // reboot   d:fn
@@ -2595,9 +2680,9 @@
 #undef FOR_rfkill
 #endif
 
-// rm fiRrv[-fi] fiRrv[-fi]
+// rm f(force)iRrv[-fi] f(force)iRrv[-fi]
 #undef OPTSTR_rm
-#define OPTSTR_rm "fiRrv[-fi]"
+#define OPTSTR_rm "f(force)iRrv[-fi]"
 #ifdef CLEANUP_rm
 #undef CLEANUP_rm
 #undef FOR_rm
@@ -2657,17 +2742,17 @@
 #undef FLAG_list_modes
 #endif
 
-// runcon   <2
+// runcon   ^<2
 #undef OPTSTR_runcon
-#define OPTSTR_runcon "<2"
+#define OPTSTR_runcon "^<2"
 #ifdef CLEANUP_runcon
 #undef CLEANUP_runcon
 #undef FOR_runcon
 #endif
 
-// sed (help)(version)e*f*i:;nErz(null-data)s[+Er] (help)(version)e*f*i:;nErz(null-data)s[+Er]
+// 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)e*f*i:;nErz(null-data)s[+Er]"
+#define OPTSTR_sed "(help)(version)(tarxform)e*f*i:;nErz(null-data)s[+Er]"
 #ifdef CLEANUP_sed
 #undef CLEANUP_sed
 #undef FOR_sed
@@ -2679,6 +2764,7 @@
 #undef FLAG_i
 #undef FLAG_f
 #undef FLAG_e
+#undef FLAG_tarxform
 #undef FLAG_version
 #undef FLAG_help
 #endif
@@ -2789,9 +2875,20 @@
 #undef FLAG_z
 #endif
 
-// skeleton   (walrus)(blubber):;(also):e@d*c#b:a
+// shuf   zen#<0
+#undef OPTSTR_shuf
+#define OPTSTR_shuf "zen#<0"
+#ifdef CLEANUP_shuf
+#undef CLEANUP_shuf
+#undef FOR_shuf
+#undef FLAG_n
+#undef FLAG_e
+#undef FLAG_z
+#endif
+
+// skeleton   (walrus)(blubber):;(also):h(hlong):; g(glong): f(longf):;e@d*c#b:a
 #undef OPTSTR_skeleton
-#define OPTSTR_skeleton "(walrus)(blubber):;(also):e@d*c#b:a"
+#define OPTSTR_skeleton "(walrus)(blubber):;(also):h(hlong):; g(glong): f(longf):;e@d*c#b:a"
 #ifdef CLEANUP_skeleton
 #undef CLEANUP_skeleton
 #undef FOR_skeleton
@@ -2800,6 +2897,9 @@
 #undef FLAG_c
 #undef FLAG_d
 #undef FLAG_e
+#undef FLAG_f
+#undef FLAG_g
+#undef FLAG_h
 #undef FLAG_also
 #undef FLAG_blubber
 #undef FLAG_walrus
@@ -2843,9 +2943,9 @@
 #undef FLAG_M
 #endif
 
-// sort gS:T:mo:k*t:xVbMcszdfirun gS:T:mo:k*t:xVbMcszdfirun
+// sort gS:T:mo:k*t:xVbMCcszdfirun gS:T:mo:k*t:xVbMCcszdfirun
 #undef OPTSTR_sort
-#define OPTSTR_sort "gS:T:mo:k*t:xVbMcszdfirun"
+#define OPTSTR_sort "gS:T:mo:k*t:xVbMCcszdfirun"
 #ifdef CLEANUP_sort
 #undef CLEANUP_sort
 #undef FOR_sort
@@ -2858,6 +2958,7 @@
 #undef FLAG_z
 #undef FLAG_s
 #undef FLAG_c
+#undef FLAG_C
 #undef FLAG_M
 #undef FLAG_b
 #undef FLAG_V
@@ -2962,12 +3063,14 @@
 #undef FLAG_t
 #endif
 
-// swapoff   <1>1
+// swapoff   <1>1av
 #undef OPTSTR_swapoff
-#define OPTSTR_swapoff "<1>1"
+#define OPTSTR_swapoff "<1>1av"
 #ifdef CLEANUP_swapoff
 #undef CLEANUP_swapoff
 #undef FOR_swapoff
+#undef FLAG_v
+#undef FLAG_a
 #endif
 
 // swapon   <1>1p#<0>32767d
@@ -3057,15 +3160,17 @@
 #undef FLAG_f
 #endif
 
-// tar &(strip-components)#(selinux)(restrict)(full-time)(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mode):(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)I(use-compress-program):J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):a[!txc][!jzJa] &(strip-components)#(selinux)(restrict)(full-time)(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mode):(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)I(use-compress-program):J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):a[!txc][!jzJa]
+// tar &(no-ignore-case)(ignore-case)(no-anchored)(anchored)(no-wildcards)(wildcards)(no-wildcards-match-slash)(wildcards-match-slash)(show-transformed-names)(selinux)(restrict)(full-time)(no-recursion)(null)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(sort);:(mode):(mtime):(group):(owner):(to-command):~(strip-components)(strip)#~(transform)(xform)*o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*I(use-compress-program):C(directory):f(file):as[!txc][!jzJa] &(no-ignore-case)(ignore-case)(no-anchored)(anchored)(no-wildcards)(wildcards)(no-wildcards-match-slash)(wildcards-match-slash)(show-transformed-names)(selinux)(restrict)(full-time)(no-recursion)(null)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(sort);:(mode):(mtime):(group):(owner):(to-command):~(strip-components)(strip)#~(transform)(xform)*o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*I(use-compress-program):C(directory):f(file):as[!txc][!jzJa]
 #undef OPTSTR_tar
-#define OPTSTR_tar "&(strip-components)#(selinux)(restrict)(full-time)(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mode):(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)I(use-compress-program):J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):a[!txc][!jzJa]"
+#define OPTSTR_tar "&(no-ignore-case)(ignore-case)(no-anchored)(anchored)(no-wildcards)(wildcards)(no-wildcards-match-slash)(wildcards-match-slash)(show-transformed-names)(selinux)(restrict)(full-time)(no-recursion)(null)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(sort);:(mode):(mtime):(group):(owner):(to-command):~(strip-components)(strip)#~(transform)(xform)*o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*I(use-compress-program):C(directory):f(file):as[!txc][!jzJa]"
 #ifdef CLEANUP_tar
 #undef CLEANUP_tar
 #undef FOR_tar
+#undef FLAG_s
 #undef FLAG_a
 #undef FLAG_f
 #undef FLAG_C
+#undef FLAG_I
 #undef FLAG_T
 #undef FLAG_X
 #undef FLAG_m
@@ -3075,7 +3180,6 @@
 #undef FLAG_z
 #undef FLAG_j
 #undef FLAG_J
-#undef FLAG_I
 #undef FLAG_v
 #undef FLAG_t
 #undef FLAG_x
@@ -3084,20 +3188,32 @@
 #undef FLAG_k
 #undef FLAG_p
 #undef FLAG_o
+#undef FLAG_xform
+#undef FLAG_strip
 #undef FLAG_to_command
 #undef FLAG_owner
 #undef FLAG_group
 #undef FLAG_mtime
 #undef FLAG_mode
+#undef FLAG_sort
 #undef FLAG_exclude
 #undef FLAG_overwrite
 #undef FLAG_no_same_permissions
 #undef FLAG_numeric_owner
+#undef FLAG_null
 #undef FLAG_no_recursion
 #undef FLAG_full_time
 #undef FLAG_restrict
 #undef FLAG_selinux
-#undef FLAG_strip_components
+#undef FLAG_show_transformed_names
+#undef FLAG_wildcards_match_slash
+#undef FLAG_no_wildcards_match_slash
+#undef FLAG_wildcards
+#undef FLAG_no_wildcards
+#undef FLAG_anchored
+#undef FLAG_no_anchored
+#undef FLAG_ignore_case
+#undef FLAG_no_ignore_case
 #endif
 
 // taskset   <1^pa
@@ -3110,9 +3226,9 @@
 #undef FLAG_p
 #endif
 
-// tcpsvd   ^<3c#=30<1C:b#=20<0u:l:hEv
+// tcpsvd   ^<3c#=30<1b#=20<0C:u:l:hEv
 #undef OPTSTR_tcpsvd
-#define OPTSTR_tcpsvd "^<3c#=30<1C:b#=20<0u:l:hEv"
+#define OPTSTR_tcpsvd "^<3c#=30<1b#=20<0C:u:l:hEv"
 #ifdef CLEANUP_tcpsvd
 #undef CLEANUP_tcpsvd
 #undef FOR_tcpsvd
@@ -3121,8 +3237,8 @@
 #undef FLAG_h
 #undef FLAG_l
 #undef FLAG_u
-#undef FLAG_b
 #undef FLAG_C
+#undef FLAG_b
 #undef FLAG_c
 #endif
 
@@ -3204,12 +3320,13 @@
 #undef FLAG_p
 #endif
 
-// timeout <2^(foreground)(preserve-status)vk:s(signal): <2^(foreground)(preserve-status)vk:s(signal):
+// timeout <2^(foreground)(preserve-status)vk:s(signal):i <2^(foreground)(preserve-status)vk:s(signal):i
 #undef OPTSTR_timeout
-#define OPTSTR_timeout "<2^(foreground)(preserve-status)vk:s(signal):"
+#define OPTSTR_timeout "<2^(foreground)(preserve-status)vk:s(signal):i"
 #ifdef CLEANUP_timeout
 #undef CLEANUP_timeout
 #undef FOR_timeout
+#undef FLAG_i
 #undef FLAG_s
 #undef FLAG_k
 #undef FLAG_v
@@ -3400,9 +3517,9 @@
 #undef FLAG_c
 #endif
 
-// uname aomvrns aomvrns
+// uname paomvrns paomvrns
 #undef OPTSTR_uname
-#define OPTSTR_uname "aomvrns"
+#define OPTSTR_uname "paomvrns"
 #ifdef CLEANUP_uname
 #undef CLEANUP_uname
 #undef FOR_uname
@@ -3413,6 +3530,7 @@
 #undef FLAG_m
 #undef FLAG_o
 #undef FLAG_a
+#undef FLAG_p
 #endif
 
 // unicode   <1
@@ -3466,9 +3584,9 @@
 #undef FLAG_f
 #endif
 
-// unshare   <1^f(fork);r(map-root-user);i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user);
+// unshare   <1^a(all)f(fork)r(map-root-user)C(cgroup):; i(ipc):; m(mount):; n(net):; p(pid):; u(uts):; U(user):; 
 #undef OPTSTR_unshare
-#define OPTSTR_unshare "<1^f(fork);r(map-root-user);i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user);"
+#define OPTSTR_unshare "<1^a(all)f(fork)r(map-root-user)C(cgroup):; i(ipc):; m(mount):; n(net):; p(pid):; u(uts):; U(user):; "
 #ifdef CLEANUP_unshare
 #undef CLEANUP_unshare
 #undef FOR_unshare
@@ -3478,8 +3596,10 @@
 #undef FLAG_n
 #undef FLAG_m
 #undef FLAG_i
+#undef FLAG_C
 #undef FLAG_r
 #undef FLAG_f
+#undef FLAG_a
 #endif
 
 // uptime   >0ps
@@ -3517,9 +3637,9 @@
 #undef FLAG_r
 #endif
 
-// usleep   <1
+// usleep   <1>1
 #undef OPTSTR_usleep
-#define OPTSTR_usleep "<1"
+#define OPTSTR_usleep "<1>1"
 #ifdef CLEANUP_usleep
 #undef CLEANUP_usleep
 #undef FOR_usleep
@@ -3661,9 +3781,9 @@
 #undef FLAG_a
 #endif
 
-// xargs ^E:P#<0=1optrn#<1(max-args)s#0[!0E] ^E:P#<0=1optrn#<1(max-args)s#0[!0E]
+// 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=1optrn#<1(max-args)s#0[!0E]"
+#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
@@ -3678,9 +3798,9 @@
 #undef FLAG_E
 #endif
 
-// xxd >1c#<0>256l#o#g#<1=2iprs#[!rs] >1c#<0>256l#o#g#<1=2iprs#[!rs]
+// xxd >1c#<0>256l#o#g#<0=2eiprs#[!rs][!re] >1c#<0>256l#o#g#<0=2eiprs#[!rs][!re]
 #undef OPTSTR_xxd
-#define OPTSTR_xxd ">1c#<0>256l#o#g#<1=2iprs#[!rs]"
+#define OPTSTR_xxd ">1c#<0>256l#o#g#<0=2eiprs#[!rs][!re]"
 #ifdef CLEANUP_xxd
 #undef CLEANUP_xxd
 #undef FOR_xxd
@@ -3688,6 +3808,7 @@
 #undef FLAG_r
 #undef FLAG_p
 #undef FLAG_i
+#undef FLAG_e
 #undef FLAG_g
 #undef FLAG_o
 #undef FLAG_l
@@ -3710,9 +3831,9 @@
 #undef FOR_yes
 #endif
 
-// zcat cdfk123456789[-123456789] cdfk123456789[-123456789]
+// zcat cdfkt123456789[-123456789] cdfkt123456789[-123456789]
 #undef OPTSTR_zcat
-#define OPTSTR_zcat "cdfk123456789[-123456789]"
+#define OPTSTR_zcat "cdfkt123456789[-123456789]"
 #ifdef CLEANUP_zcat
 #undef CLEANUP_zcat
 #undef FOR_zcat
@@ -3725,6 +3846,7 @@
 #undef FLAG_3
 #undef FLAG_2
 #undef FLAG_1
+#undef FLAG_t
 #undef FLAG_k
 #undef FLAG_f
 #undef FLAG_d
@@ -3816,8 +3938,8 @@
 #ifndef TT
 #define TT this.basename
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_a (1<<1)
+#define FLAG_s (1LL<<0)
+#define FLAG_a (1LL<<1)
 #endif
 
 #ifdef FOR_bc
@@ -3850,8 +3972,9 @@
 #define TT this.blkid
 #endif
 #define FLAG_s (FORCED_FLAG<<0)
-#define FLAG_L (FORCED_FLAG<<1)
-#define FLAG_U (FORCED_FLAG<<2)
+#define FLAG_o (FORCED_FLAG<<1)
+#define FLAG_L (FORCED_FLAG<<2)
+#define FLAG_U (FORCED_FLAG<<3)
 #endif
 
 #ifdef FOR_blockdev
@@ -3920,20 +4043,10 @@
 #ifndef TT
 #define TT this.cat
 #endif
-#define FLAG_e (1<<0)
-#define FLAG_t (1<<1)
-#define FLAG_v (1<<2)
-#define FLAG_u (1<<3)
-#endif
-
-#ifdef FOR_catv
-#define CLEANUP_catv
-#ifndef TT
-#define TT this.catv
-#endif
-#define FLAG_e (FORCED_FLAG<<0)
-#define FLAG_t (FORCED_FLAG<<1)
-#define FLAG_v (FORCED_FLAG<<2)
+#define FLAG_e (1LL<<0)
+#define FLAG_t (1LL<<1)
+#define FLAG_v (1LL<<2)
+#define FLAG_u (1LL<<3)
 #endif
 
 #ifdef FOR_cd
@@ -3984,9 +4097,9 @@
 #ifndef TT
 #define TT this.chmod
 #endif
-#define FLAG_R (1<<0)
-#define FLAG_f (1<<1)
-#define FLAG_v (1<<2)
+#define FLAG_R (1LL<<0)
+#define FLAG_f (1LL<<1)
+#define FLAG_v (1LL<<2)
 #endif
 
 #ifdef FOR_chroot
@@ -4050,9 +4163,9 @@
 #ifndef TT
 #define TT this.cmp
 #endif
-#define FLAG_n (1<<0)
-#define FLAG_s (1<<1)
-#define FLAG_l (1<<2)
+#define FLAG_n (1LL<<0)
+#define FLAG_s (1LL<<1)
+#define FLAG_l (1LL<<2)
 #endif
 
 #ifdef FOR_comm
@@ -4060,9 +4173,9 @@
 #ifndef TT
 #define TT this.comm
 #endif
-#define FLAG_1 (1<<0)
-#define FLAG_2 (1<<1)
-#define FLAG_3 (1<<2)
+#define FLAG_1 (1LL<<0)
+#define FLAG_2 (1LL<<1)
+#define FLAG_3 (1LL<<2)
 #endif
 
 #ifdef FOR_count
@@ -4077,26 +4190,26 @@
 #ifndef TT
 #define TT this.cp
 #endif
-#define FLAG_T (1<<0)
-#define FLAG_t (1<<1)
-#define FLAG_i (1<<2)
-#define FLAG_f (1<<3)
-#define FLAG_F (1<<4)
-#define FLAG_n (1<<5)
-#define FLAG_v (1<<6)
-#define FLAG_l (1<<7)
-#define FLAG_s (1<<8)
-#define FLAG_a (1<<9)
-#define FLAG_d (1<<10)
-#define FLAG_u (1<<11)
-#define FLAG_r (1<<12)
-#define FLAG_p (1<<13)
-#define FLAG_P (1<<14)
-#define FLAG_L (1<<15)
-#define FLAG_H (1<<16)
-#define FLAG_R (1<<17)
-#define FLAG_D (1<<18)
-#define FLAG_preserve (1<<19)
+#define FLAG_T (1LL<<0)
+#define FLAG_t (1LL<<1)
+#define FLAG_i (1LL<<2)
+#define FLAG_f (1LL<<3)
+#define FLAG_F (1LL<<4)
+#define FLAG_n (1LL<<5)
+#define FLAG_v (1LL<<6)
+#define FLAG_l (1LL<<7)
+#define FLAG_s (1LL<<8)
+#define FLAG_a (1LL<<9)
+#define FLAG_d (1LL<<10)
+#define FLAG_u (1LL<<11)
+#define FLAG_r (1LL<<12)
+#define FLAG_p (1LL<<13)
+#define FLAG_P (1LL<<14)
+#define FLAG_L (1LL<<15)
+#define FLAG_H (1LL<<16)
+#define FLAG_R (1LL<<17)
+#define FLAG_D (1LL<<18)
+#define FLAG_preserve (1LL<<19)
 #endif
 
 #ifdef FOR_cpio
@@ -4104,20 +4217,21 @@
 #ifndef TT
 #define TT this.cpio
 #endif
-#define FLAG_o (1<<0)
-#define FLAG_v (1<<1)
-#define FLAG_F (1<<2)
-#define FLAG_t (1<<3)
-#define FLAG_i (1<<4)
-#define FLAG_p (1<<5)
-#define FLAG_H (1<<6)
-#define FLAG_u (1<<7)
-#define FLAG_d (1<<8)
-#define FLAG_m (1<<9)
-#define FLAG_no_preserve_owner (1<<10)
-#define FLAG_quiet (1<<11)
-#define FLAG_renumber_inodes (1<<12)
-#define FLAG_ignore_devno (1<<13)
+#define FLAG_o (1LL<<0)
+#define FLAG_v (1LL<<1)
+#define FLAG_F (1LL<<2)
+#define FLAG_t (1LL<<3)
+#define FLAG_i (1LL<<4)
+#define FLAG_p (1LL<<5)
+#define FLAG_H (1LL<<6)
+#define FLAG_u (1LL<<7)
+#define FLAG_d (1LL<<8)
+#define FLAG_m (1LL<<9)
+#define FLAG_R (1LL<<10)
+#define FLAG_no_preserve_owner (1LL<<11)
+#define FLAG_quiet (1LL<<12)
+#define FLAG_renumber_inodes (1LL<<13)
+#define FLAG_ignore_devno (1LL<<14)
 #endif
 
 #ifdef FOR_crc32
@@ -4158,16 +4272,16 @@
 #ifndef TT
 #define TT this.cut
 #endif
-#define FLAG_n (1<<0)
-#define FLAG_D (1<<1)
-#define FLAG_s (1<<2)
-#define FLAG_d (1<<3)
-#define FLAG_O (1<<4)
-#define FLAG_C (1<<5)
-#define FLAG_F (1<<6)
-#define FLAG_f (1<<7)
-#define FLAG_c (1<<8)
-#define FLAG_b (1<<9)
+#define FLAG_n (1LL<<0)
+#define FLAG_D (1LL<<1)
+#define FLAG_s (1LL<<2)
+#define FLAG_d (1LL<<3)
+#define FLAG_O (1LL<<4)
+#define FLAG_C (1LL<<5)
+#define FLAG_F (1LL<<6)
+#define FLAG_f (1LL<<7)
+#define FLAG_c (1LL<<8)
+#define FLAG_b (1LL<<9)
 #endif
 
 #ifdef FOR_date
@@ -4175,12 +4289,12 @@
 #ifndef TT
 #define TT this.date
 #endif
-#define FLAG_u (1<<0)
-#define FLAG_s (1<<1)
-#define FLAG_r (1<<2)
-#define FLAG_I (1<<3)
-#define FLAG_D (1<<4)
-#define FLAG_d (1<<5)
+#define FLAG_u (1LL<<0)
+#define FLAG_s (1LL<<1)
+#define FLAG_r (1LL<<2)
+#define FLAG_I (1LL<<3)
+#define FLAG_D (1LL<<4)
+#define FLAG_d (1LL<<5)
 #endif
 
 #ifdef FOR_dd
@@ -4249,27 +4363,27 @@
 #define FLAG_C (FORCED_FLAG<<28)
 #define FLAG_D (FORCED_FLAG<<29)
 #define FLAG_E (FORCED_FLAG<<30)
-#define FLAG_F (FORCED_FLAGLL<<31)
-#define FLAG_G (FORCED_FLAGLL<<32)
-#define FLAG_H (FORCED_FLAGLL<<33)
-#define FLAG_I (FORCED_FLAGLL<<34)
-#define FLAG_J (FORCED_FLAGLL<<35)
-#define FLAG_K (FORCED_FLAGLL<<36)
-#define FLAG_L (FORCED_FLAGLL<<37)
-#define FLAG_M (FORCED_FLAGLL<<38)
-#define FLAG_N (FORCED_FLAGLL<<39)
-#define FLAG_O (FORCED_FLAGLL<<40)
-#define FLAG_P (FORCED_FLAGLL<<41)
-#define FLAG_Q (FORCED_FLAGLL<<42)
-#define FLAG_R (FORCED_FLAGLL<<43)
-#define FLAG_S (FORCED_FLAGLL<<44)
-#define FLAG_T (FORCED_FLAGLL<<45)
-#define FLAG_U (FORCED_FLAGLL<<46)
-#define FLAG_V (FORCED_FLAGLL<<47)
-#define FLAG_W (FORCED_FLAGLL<<48)
-#define FLAG_X (FORCED_FLAGLL<<49)
-#define FLAG_Y (FORCED_FLAGLL<<50)
-#define FLAG_Z (FORCED_FLAGLL<<51)
+#define FLAG_F (FORCED_FLAG<<31)
+#define FLAG_G (FORCED_FLAG<<32)
+#define FLAG_H (FORCED_FLAG<<33)
+#define FLAG_I (FORCED_FLAG<<34)
+#define FLAG_J (FORCED_FLAG<<35)
+#define FLAG_K (FORCED_FLAG<<36)
+#define FLAG_L (FORCED_FLAG<<37)
+#define FLAG_M (FORCED_FLAG<<38)
+#define FLAG_N (FORCED_FLAG<<39)
+#define FLAG_O (FORCED_FLAG<<40)
+#define FLAG_P (FORCED_FLAG<<41)
+#define FLAG_Q (FORCED_FLAG<<42)
+#define FLAG_R (FORCED_FLAG<<43)
+#define FLAG_S (FORCED_FLAG<<44)
+#define FLAG_T (FORCED_FLAG<<45)
+#define FLAG_U (FORCED_FLAG<<46)
+#define FLAG_V (FORCED_FLAG<<47)
+#define FLAG_W (FORCED_FLAG<<48)
+#define FLAG_X (FORCED_FLAG<<49)
+#define FLAG_Y (FORCED_FLAG<<50)
+#define FLAG_Z (FORCED_FLAG<<51)
 #endif
 
 #ifdef FOR_demo_number
@@ -4390,24 +4504,28 @@
 #ifndef TT
 #define TT this.diff
 #endif
-#define FLAG_U (1<<0)
-#define FLAG_r (1<<1)
-#define FLAG_N (1<<2)
-#define FLAG_S (1<<3)
-#define FLAG_L (1<<4)
-#define FLAG_a (1<<5)
-#define FLAG_q (1<<6)
-#define FLAG_s (1<<7)
-#define FLAG_T (1<<8)
-#define FLAG_i (1<<9)
-#define FLAG_w (1<<10)
-#define FLAG_t (1<<11)
-#define FLAG_u (1<<12)
-#define FLAG_b (1<<13)
-#define FLAG_d (1<<14)
-#define FLAG_B (1<<15)
-#define FLAG_strip_trailing_cr (1<<16)
-#define FLAG_color (1<<17)
+#define FLAG_U (1LL<<0)
+#define FLAG_r (1LL<<1)
+#define FLAG_N (1LL<<2)
+#define FLAG_L (1LL<<3)
+#define FLAG_F (1LL<<4)
+#define FLAG_S (1LL<<5)
+#define FLAG_a (1LL<<6)
+#define FLAG_q (1LL<<7)
+#define FLAG_s (1LL<<8)
+#define FLAG_T (1LL<<9)
+#define FLAG_i (1LL<<10)
+#define FLAG_w (1LL<<11)
+#define FLAG_t (1LL<<12)
+#define FLAG_u (1LL<<13)
+#define FLAG_b (1LL<<14)
+#define FLAG_d (1LL<<15)
+#define FLAG_B (1LL<<16)
+#define FLAG_strip_trailing_cr (1LL<<17)
+#define FLAG_color (1LL<<18)
+#define FLAG_new_line_format (1LL<<19)
+#define FLAG_old_line_format (1LL<<20)
+#define FLAG_unchanged_line_format (1LL<<21)
 #endif
 
 #ifdef FOR_dirname
@@ -4452,19 +4570,19 @@
 #ifndef TT
 #define TT this.du
 #endif
-#define FLAG_b (1<<0)
-#define FLAG_x (1<<1)
-#define FLAG_s (1<<2)
-#define FLAG_L (1<<3)
-#define FLAG_K (1<<4)
-#define FLAG_k (1<<5)
-#define FLAG_H (1<<6)
-#define FLAG_a (1<<7)
-#define FLAG_c (1<<8)
-#define FLAG_l (1<<9)
-#define FLAG_m (1<<10)
-#define FLAG_h (1<<11)
-#define FLAG_d (1<<12)
+#define FLAG_b (1LL<<0)
+#define FLAG_x (1LL<<1)
+#define FLAG_s (1LL<<2)
+#define FLAG_L (1LL<<3)
+#define FLAG_K (1LL<<4)
+#define FLAG_k (1LL<<5)
+#define FLAG_H (1LL<<6)
+#define FLAG_a (1LL<<7)
+#define FLAG_c (1LL<<8)
+#define FLAG_l (1LL<<9)
+#define FLAG_m (1LL<<10)
+#define FLAG_h (1LL<<11)
+#define FLAG_d (1LL<<12)
 #endif
 
 #ifdef FOR_dumpleases
@@ -4482,9 +4600,9 @@
 #ifndef TT
 #define TT this.echo
 #endif
-#define FLAG_n (1<<0)
-#define FLAG_e (1<<1)
-#define FLAG_E (1<<2)
+#define FLAG_n (1LL<<0)
+#define FLAG_e (1LL<<1)
+#define FLAG_E (1LL<<2)
 #endif
 
 #ifdef FOR_eject
@@ -4502,9 +4620,9 @@
 #ifndef TT
 #define TT this.env
 #endif
-#define FLAG_u (1<<0)
-#define FLAG_0 (1<<1)
-#define FLAG_i (1<<2)
+#define FLAG_u (1LL<<0)
+#define FLAG_0 (1LL<<1)
+#define FLAG_i (1LL<<2)
 #endif
 
 #ifdef FOR_eval
@@ -4560,6 +4678,8 @@
 #ifndef TT
 #define TT this.factor
 #endif
+#define FLAG_x (FORCED_FLAG<<0)
+#define FLAG_h (FORCED_FLAG<<1)
 #endif
 
 #ifdef FOR_fallocate
@@ -4596,10 +4716,10 @@
 #ifndef TT
 #define TT this.file
 #endif
-#define FLAG_s (FORCED_FLAG<<0)
-#define FLAG_L (FORCED_FLAG<<1)
-#define FLAG_h (FORCED_FLAG<<2)
-#define FLAG_b (FORCED_FLAG<<3)
+#define FLAG_s (1LL<<0)
+#define FLAG_L (1LL<<1)
+#define FLAG_h (1LL<<2)
+#define FLAG_b (1LL<<3)
 #endif
 
 #ifdef FOR_find
@@ -4607,8 +4727,8 @@
 #ifndef TT
 #define TT this.find
 #endif
-#define FLAG_L (1<<0)
-#define FLAG_H (1<<1)
+#define FLAG_L (1LL<<0)
+#define FLAG_H (1LL<<1)
 #endif
 
 #ifdef FOR_flock
@@ -4725,8 +4845,8 @@
 #ifndef TT
 #define TT this.getconf
 #endif
-#define FLAG_l (1<<0)
-#define FLAG_a (1<<1)
+#define FLAG_l (1LL<<0)
+#define FLAG_a (1LL<<1)
 #endif
 
 #ifdef FOR_getenforce
@@ -4752,12 +4872,12 @@
 #ifndef TT
 #define TT this.getopt
 #endif
-#define FLAG_u (1<<0)
-#define FLAG_T (1<<1)
-#define FLAG_l (1<<2)
-#define FLAG_o (1<<3)
-#define FLAG_n (1<<4)
-#define FLAG_a (1<<5)
+#define FLAG_u (1LL<<0)
+#define FLAG_T (1LL<<1)
+#define FLAG_l (1LL<<2)
+#define FLAG_o (1LL<<3)
+#define FLAG_n (1LL<<4)
+#define FLAG_a (1LL<<5)
 #endif
 
 #ifdef FOR_getty
@@ -4778,6 +4898,41 @@
 #define FLAG_t (FORCED_FLAG<<10)
 #endif
 
+#ifdef FOR_gitcheckout
+#define CLEANUP_gitcheckout
+#ifndef TT
+#define TT this.gitcheckout
+#endif
+#endif
+
+#ifdef FOR_gitclone
+#define CLEANUP_gitclone
+#ifndef TT
+#define TT this.gitclone
+#endif
+#endif
+
+#ifdef FOR_gitfetch
+#define CLEANUP_gitfetch
+#ifndef TT
+#define TT this.gitfetch
+#endif
+#endif
+
+#ifdef FOR_gitinit
+#define CLEANUP_gitinit
+#ifndef TT
+#define TT this.gitinit
+#endif
+#endif
+
+#ifdef FOR_gitremote
+#define CLEANUP_gitremote
+#ifndef TT
+#define TT this.gitremote
+#endif
+#endif
+
 #ifdef FOR_gpiodetect
 #define CLEANUP_gpiodetect
 #ifndef TT
@@ -4820,37 +4975,37 @@
 #ifndef TT
 #define TT this.grep
 #endif
-#define FLAG_x (1<<0)
-#define FLAG_m (1<<1)
-#define FLAG_A (1<<2)
-#define FLAG_B (1<<3)
-#define FLAG_C (1<<4)
-#define FLAG_f (1<<5)
-#define FLAG_e (1<<6)
-#define FLAG_q (1<<7)
-#define FLAG_l (1<<8)
-#define FLAG_L (1<<9)
-#define FLAG_c (1<<10)
-#define FLAG_w (1<<11)
-#define FLAG_v (1<<12)
-#define FLAG_s (1<<13)
-#define FLAG_R (1<<14)
-#define FLAG_r (1<<15)
-#define FLAG_o (1<<16)
-#define FLAG_n (1<<17)
-#define FLAG_i (1<<18)
-#define FLAG_h (1<<19)
-#define FLAG_b (1<<20)
-#define FLAG_a (1<<21)
-#define FLAG_I (1<<22)
-#define FLAG_H (1<<23)
-#define FLAG_F (1<<24)
-#define FLAG_E (1<<25)
-#define FLAG_z (1<<26)
-#define FLAG_Z (1<<27)
-#define FLAG_M (1<<28)
-#define FLAG_S (1<<29)
-#define FLAG_exclude_dir (1<<30)
+#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
@@ -4892,10 +5047,11 @@
 #define FLAG_3 (FORCED_FLAG<<6)
 #define FLAG_2 (FORCED_FLAG<<7)
 #define FLAG_1 (FORCED_FLAG<<8)
-#define FLAG_k (FORCED_FLAG<<9)
-#define FLAG_f (FORCED_FLAG<<10)
-#define FLAG_d (FORCED_FLAG<<11)
-#define FLAG_c (FORCED_FLAG<<12)
+#define FLAG_t (FORCED_FLAG<<9)
+#define FLAG_k (FORCED_FLAG<<10)
+#define FLAG_f (FORCED_FLAG<<11)
+#define FLAG_d (FORCED_FLAG<<12)
+#define FLAG_c (FORCED_FLAG<<13)
 #endif
 
 #ifdef FOR_gzip
@@ -4903,20 +5059,21 @@
 #ifndef TT
 #define TT this.gzip
 #endif
-#define FLAG_9 (1<<0)
-#define FLAG_8 (1<<1)
-#define FLAG_7 (1<<2)
-#define FLAG_6 (1<<3)
-#define FLAG_5 (1<<4)
-#define FLAG_4 (1<<5)
-#define FLAG_3 (1<<6)
-#define FLAG_2 (1<<7)
-#define FLAG_1 (1<<8)
-#define FLAG_k (1<<9)
-#define FLAG_f (1<<10)
-#define FLAG_d (1<<11)
-#define FLAG_c (1<<12)
-#define FLAG_n (1<<13)
+#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
@@ -4924,10 +5081,10 @@
 #ifndef TT
 #define TT this.head
 #endif
-#define FLAG_v (1<<0)
-#define FLAG_q (1<<1)
-#define FLAG_c (1<<2)
-#define FLAG_n (1<<3)
+#define FLAG_v (1LL<<0)
+#define FLAG_q (1LL<<1)
+#define FLAG_c (1LL<<2)
+#define FLAG_n (1LL<<3)
 #endif
 
 #ifdef FOR_hello
@@ -4993,11 +5150,19 @@
 #ifndef TT
 #define TT this.hostname
 #endif
-#define FLAG_F (1<<0)
-#define FLAG_f (1<<1)
-#define FLAG_s (1<<2)
-#define FLAG_d (1<<3)
-#define FLAG_b (1<<4)
+#define FLAG_F (1LL<<0)
+#define FLAG_f (1LL<<1)
+#define FLAG_s (1LL<<2)
+#define FLAG_d (1LL<<3)
+#define FLAG_b (1LL<<4)
+#endif
+
+#ifdef FOR_httpd
+#define CLEANUP_httpd
+#ifndef TT
+#define TT this.httpd
+#endif
+#define FLAG_v (FORCED_FLAG<<0)
 #endif
 
 #ifdef FOR_hwclock
@@ -5071,11 +5236,11 @@
 #ifndef TT
 #define TT this.id
 #endif
-#define FLAG_u (1<<0)
-#define FLAG_r (1<<1)
-#define FLAG_g (1<<2)
-#define FLAG_G (1<<3)
-#define FLAG_n (1<<4)
+#define FLAG_u (1LL<<0)
+#define FLAG_r (1LL<<1)
+#define FLAG_g (1LL<<2)
+#define FLAG_G (1LL<<3)
+#define FLAG_n (1LL<<4)
 #define FLAG_Z (FORCED_FLAG<<5)
 #endif
 
@@ -5114,16 +5279,16 @@
 #ifndef TT
 #define TT this.install
 #endif
-#define FLAG_g (1<<0)
-#define FLAG_o (1<<1)
-#define FLAG_m (1<<2)
-#define FLAG_t (1<<3)
-#define FLAG_v (1<<4)
-#define FLAG_s (1<<5)
-#define FLAG_p (1<<6)
-#define FLAG_D (1<<7)
-#define FLAG_d (1<<8)
-#define FLAG_c (1<<9)
+#define FLAG_g (1LL<<0)
+#define FLAG_o (1LL<<1)
+#define FLAG_m (1LL<<2)
+#define FLAG_t (1LL<<3)
+#define FLAG_v (1LL<<4)
+#define FLAG_s (1LL<<5)
+#define FLAG_p (1LL<<6)
+#define FLAG_D (1LL<<7)
+#define FLAG_d (1LL<<8)
+#define FLAG_c (1LL<<9)
 #endif
 
 #ifdef FOR_ionice
@@ -5284,13 +5449,13 @@
 #ifndef TT
 #define TT this.ln
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_f (1<<1)
-#define FLAG_n (1<<2)
-#define FLAG_v (1<<3)
-#define FLAG_T (1<<4)
-#define FLAG_t (1<<5)
-#define FLAG_r (1<<6)
+#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_load_policy
@@ -5365,39 +5530,45 @@
 #ifndef TT
 #define TT this.ls
 #endif
-#define FLAG_1 (1<<0)
-#define FLAG_x (1<<1)
-#define FLAG_w (1<<2)
-#define FLAG_u (1<<3)
-#define FLAG_t (1<<4)
-#define FLAG_s (1<<5)
-#define FLAG_r (1<<6)
-#define FLAG_q (1<<7)
-#define FLAG_p (1<<8)
-#define FLAG_n (1<<9)
-#define FLAG_m (1<<10)
-#define FLAG_l (1<<11)
-#define FLAG_k (1<<12)
-#define FLAG_i (1<<13)
-#define FLAG_h (1<<14)
-#define FLAG_f (1<<15)
-#define FLAG_d (1<<16)
-#define FLAG_c (1<<17)
-#define FLAG_b (1<<18)
-#define FLAG_a (1<<19)
-#define FLAG_S (1<<20)
-#define FLAG_R (1<<21)
-#define FLAG_L (1<<22)
-#define FLAG_H (1<<23)
-#define FLAG_F (1<<24)
-#define FLAG_C (1<<25)
-#define FLAG_A (1<<26)
-#define FLAG_o (1<<27)
-#define FLAG_g (1<<28)
-#define FLAG_Z (1<<29)
-#define FLAG_show_control_chars (1<<30)
-#define FLAG_full_time (1LL<<31)
-#define FLAG_color (1LL<<32)
+#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_show_control_chars (1LL<<35)
+#define FLAG_full_time (1LL<<36)
+#define FLAG_color (1LL<<37)
+#define FLAG_sort (1LL<<38)
 #endif
 
 #ifdef FOR_lsattr
@@ -5436,10 +5607,11 @@
 #define TT this.lspci
 #endif
 #define FLAG_i (FORCED_FLAG<<0)
-#define FLAG_n (FORCED_FLAG<<1)
-#define FLAG_k (FORCED_FLAG<<2)
-#define FLAG_m (FORCED_FLAG<<3)
-#define FLAG_e (FORCED_FLAG<<4)
+#define FLAG_x (FORCED_FLAG<<1)
+#define FLAG_n (FORCED_FLAG<<2)
+#define FLAG_k (FORCED_FLAG<<3)
+#define FLAG_m (FORCED_FLAG<<4)
+#define FLAG_e (FORCED_FLAG<<5)
 #endif
 
 #ifdef FOR_lsusb
@@ -5481,9 +5653,9 @@
 #ifndef TT
 #define TT this.md5sum
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_c (1<<1)
-#define FLAG_b (1<<2)
+#define FLAG_s (1LL<<0)
+#define FLAG_c (1LL<<1)
+#define FLAG_b (1LL<<2)
 #endif
 
 #ifdef FOR_mdev
@@ -5499,8 +5671,8 @@
 #ifndef TT
 #define TT this.microcom
 #endif
-#define FLAG_X (1<<0)
-#define FLAG_s (1<<1)
+#define FLAG_X (1LL<<0)
+#define FLAG_s (1LL<<1)
 #endif
 
 #ifdef FOR_mix
@@ -5519,9 +5691,9 @@
 #ifndef TT
 #define TT this.mkdir
 #endif
-#define FLAG_m (1<<0)
-#define FLAG_p (1<<1)
-#define FLAG_v (1<<2)
+#define FLAG_m (1LL<<0)
+#define FLAG_p (1LL<<1)
+#define FLAG_v (1LL<<2)
 #define FLAG_Z (FORCED_FLAG<<3)
 #endif
 
@@ -5581,12 +5753,12 @@
 #ifndef TT
 #define TT this.mktemp
 #endif
-#define FLAG_t (1<<0)
-#define FLAG_p (1<<1)
-#define FLAG_d (1<<2)
-#define FLAG_q (1<<3)
-#define FLAG_u (1<<4)
-#define FLAG_tmpdir (1<<5)
+#define FLAG_t (1LL<<0)
+#define FLAG_p (1LL<<1)
+#define FLAG_d (1LL<<2)
+#define FLAG_q (1LL<<3)
+#define FLAG_u (1LL<<4)
+#define FLAG_tmpdir (1LL<<5)
 #endif
 
 #ifdef FOR_modinfo
@@ -5637,6 +5809,7 @@
 #define FLAG_f (FORCED_FLAG<<6)
 #define FLAG_a (FORCED_FLAG<<7)
 #define FLAG_O (FORCED_FLAG<<8)
+#define FLAG_R (FORCED_FLAG<<9)
 #endif
 
 #ifdef FOR_mountpoint
@@ -5654,13 +5827,13 @@
 #ifndef TT
 #define TT this.mv
 #endif
-#define FLAG_T (1<<0)
-#define FLAG_t (1<<1)
-#define FLAG_i (1<<2)
-#define FLAG_f (1<<3)
-#define FLAG_F (1<<4)
-#define FLAG_n (1<<5)
-#define FLAG_v (1<<6)
+#define FLAG_T (1LL<<0)
+#define FLAG_t (1LL<<1)
+#define FLAG_i (1LL<<2)
+#define FLAG_f (1LL<<3)
+#define FLAG_F (1LL<<4)
+#define FLAG_n (1LL<<5)
+#define FLAG_v (1LL<<6)
 #endif
 
 #ifdef FOR_nbd_client
@@ -5670,6 +5843,15 @@
 #endif
 #define FLAG_s (FORCED_FLAG<<0)
 #define FLAG_n (FORCED_FLAG<<1)
+#define FLAG_b (FORCED_FLAG<<2)
+#endif
+
+#ifdef FOR_nbd_server
+#define CLEANUP_nbd_server
+#ifndef TT
+#define TT this.nbd_server
+#endif
+#define FLAG_r (FORCED_FLAG<<0)
 #endif
 
 #ifdef FOR_netcat
@@ -5677,20 +5859,21 @@
 #ifndef TT
 #define TT this.netcat
 #endif
-#define FLAG_U (FORCED_FLAG<<0)
-#define FLAG_u (FORCED_FLAG<<1)
-#define FLAG_6 (FORCED_FLAG<<2)
-#define FLAG_4 (FORCED_FLAG<<3)
-#define FLAG_f (FORCED_FLAG<<4)
-#define FLAG_s (FORCED_FLAG<<5)
-#define FLAG_q (FORCED_FLAG<<6)
-#define FLAG_p (FORCED_FLAG<<7)
-#define FLAG_W (FORCED_FLAG<<8)
-#define FLAG_w (FORCED_FLAG<<9)
-#define FLAG_L (FORCED_FLAG<<10)
-#define FLAG_l (FORCED_FLAG<<11)
-#define FLAG_E (FORCED_FLAG<<12)
-#define FLAG_t (FORCED_FLAG<<13)
+#define FLAG_n (FORCED_FLAG<<0)
+#define FLAG_U (FORCED_FLAG<<1)
+#define FLAG_u (FORCED_FLAG<<2)
+#define FLAG_6 (FORCED_FLAG<<3)
+#define FLAG_4 (FORCED_FLAG<<4)
+#define FLAG_f (FORCED_FLAG<<5)
+#define FLAG_s (FORCED_FLAG<<6)
+#define FLAG_q (FORCED_FLAG<<7)
+#define FLAG_p (FORCED_FLAG<<8)
+#define FLAG_W (FORCED_FLAG<<9)
+#define FLAG_w (FORCED_FLAG<<10)
+#define FLAG_L (FORCED_FLAG<<11)
+#define FLAG_l (FORCED_FLAG<<12)
+#define FLAG_E (FORCED_FLAG<<13)
+#define FLAG_t (FORCED_FLAG<<14)
 #endif
 
 #ifdef FOR_netstat
@@ -5724,13 +5907,13 @@
 #ifndef TT
 #define TT this.nl
 #endif
-#define FLAG_E (1<<0)
-#define FLAG_s (1<<1)
-#define FLAG_n (1<<2)
-#define FLAG_b (1<<3)
-#define FLAG_w (1<<4)
-#define FLAG_l (1<<5)
-#define FLAG_v (1<<6)
+#define FLAG_E (1LL<<0)
+#define FLAG_s (1LL<<1)
+#define FLAG_n (1LL<<2)
+#define FLAG_b (1LL<<3)
+#define FLAG_w (1LL<<4)
+#define FLAG_l (1LL<<5)
+#define FLAG_v (1LL<<6)
 #endif
 
 #ifdef FOR_nohup
@@ -5745,7 +5928,7 @@
 #ifndef TT
 #define TT this.nproc
 #endif
-#define FLAG_all (1<<0)
+#define FLAG_all (1LL<<0)
 #endif
 
 #ifdef FOR_nsenter
@@ -5759,8 +5942,10 @@
 #define FLAG_n (FORCED_FLAG<<3)
 #define FLAG_m (FORCED_FLAG<<4)
 #define FLAG_i (FORCED_FLAG<<5)
-#define FLAG_t (FORCED_FLAG<<6)
-#define FLAG_F (FORCED_FLAG<<7)
+#define FLAG_C (FORCED_FLAG<<6)
+#define FLAG_t (FORCED_FLAG<<7)
+#define FLAG_F (FORCED_FLAG<<8)
+#define FLAG_a (FORCED_FLAG<<9)
 #endif
 
 #ifdef FOR_od
@@ -5768,18 +5953,18 @@
 #ifndef TT
 #define TT this.od
 #endif
-#define FLAG_t (1<<0)
-#define FLAG_A (1<<1)
-#define FLAG_b (1<<2)
-#define FLAG_c (1<<3)
-#define FLAG_d (1<<4)
-#define FLAG_o (1<<5)
-#define FLAG_s (1<<6)
-#define FLAG_x (1<<7)
-#define FLAG_N (1<<8)
-#define FLAG_w (1<<9)
-#define FLAG_v (1<<10)
-#define FLAG_j (1<<11)
+#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_oneit
@@ -5826,8 +6011,8 @@
 #ifndef TT
 #define TT this.paste
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_d (1<<1)
+#define FLAG_s (1LL<<0)
+#define FLAG_d (1LL<<1)
 #endif
 
 #ifdef FOR_patch
@@ -5835,19 +6020,19 @@
 #ifndef TT
 #define TT this.patch
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_R (1<<1)
-#define FLAG_i (1<<2)
-#define FLAG_d (1<<3)
-#define FLAG_p (1<<4)
-#define FLAG_l (1<<5)
-#define FLAG_u (1<<6)
-#define FLAG_f (1<<7)
-#define FLAG_g (1<<8)
-#define FLAG_F (1<<9)
+#define FLAG_s (1LL<<0)
+#define FLAG_R (1LL<<1)
+#define FLAG_i (1LL<<2)
+#define FLAG_d (1LL<<3)
+#define FLAG_p (1LL<<4)
+#define FLAG_l (1LL<<5)
+#define FLAG_u (1LL<<6)
+#define FLAG_f (1LL<<7)
+#define FLAG_g (1LL<<8)
+#define FLAG_F (1LL<<9)
 #define FLAG_x (FORCED_FLAG<<10)
-#define FLAG_dry_run (1<<11)
-#define FLAG_no_backup_if_mismatch (1<<12)
+#define FLAG_dry_run (1LL<<11)
+#define FLAG_no_backup_if_mismatch (1LL<<12)
 #endif
 
 #ifdef FOR_pgrep
@@ -5855,22 +6040,22 @@
 #ifndef TT
 #define TT this.pgrep
 #endif
-#define FLAG_L (1<<0)
-#define FLAG_x (1<<1)
-#define FLAG_v (1<<2)
-#define FLAG_o (1<<3)
-#define FLAG_n (1<<4)
-#define FLAG_f (1<<5)
-#define FLAG_G (1<<6)
-#define FLAG_g (1<<7)
-#define FLAG_P (1<<8)
-#define FLAG_s (1<<9)
-#define FLAG_t (1<<10)
-#define FLAG_U (1<<11)
-#define FLAG_u (1<<12)
-#define FLAG_d (1<<13)
-#define FLAG_l (1<<14)
-#define FLAG_c (1<<15)
+#define FLAG_L (1LL<<0)
+#define FLAG_x (1LL<<1)
+#define FLAG_v (1LL<<2)
+#define FLAG_o (1LL<<3)
+#define FLAG_n (1LL<<4)
+#define FLAG_f (1LL<<5)
+#define FLAG_G (1LL<<6)
+#define FLAG_g (1LL<<7)
+#define FLAG_P (1LL<<8)
+#define FLAG_s (1LL<<9)
+#define FLAG_t (1LL<<10)
+#define FLAG_U (1LL<<11)
+#define FLAG_u (1LL<<12)
+#define FLAG_d (1LL<<13)
+#define FLAG_l (1LL<<14)
+#define FLAG_c (1LL<<15)
 #endif
 
 #ifdef FOR_pidof
@@ -5914,20 +6099,20 @@
 #ifndef TT
 #define TT this.pkill
 #endif
-#define FLAG_l (1<<0)
-#define FLAG_x (1<<1)
-#define FLAG_v (1<<2)
-#define FLAG_o (1<<3)
-#define FLAG_n (1<<4)
-#define FLAG_f (1<<5)
-#define FLAG_G (1<<6)
-#define FLAG_g (1<<7)
-#define FLAG_P (1<<8)
-#define FLAG_s (1<<9)
-#define FLAG_t (1<<10)
-#define FLAG_U (1<<11)
-#define FLAG_u (1<<12)
-#define FLAG_V (1<<13)
+#define FLAG_l (1LL<<0)
+#define FLAG_x (1LL<<1)
+#define FLAG_v (1LL<<2)
+#define FLAG_o (1LL<<3)
+#define FLAG_n (1LL<<4)
+#define FLAG_f (1LL<<5)
+#define FLAG_G (1LL<<6)
+#define FLAG_g (1LL<<7)
+#define FLAG_P (1LL<<8)
+#define FLAG_s (1LL<<9)
+#define FLAG_t (1LL<<10)
+#define FLAG_U (1LL<<11)
+#define FLAG_u (1LL<<12)
+#define FLAG_V (1LL<<13)
 #endif
 
 #ifdef FOR_pmap
@@ -5961,28 +6146,28 @@
 #ifndef TT
 #define TT this.ps
 #endif
-#define FLAG_Z (1<<0)
-#define FLAG_w (1<<1)
-#define FLAG_G (1<<2)
-#define FLAG_g (1<<3)
-#define FLAG_U (1<<4)
-#define FLAG_u (1<<5)
-#define FLAG_T (1<<6)
-#define FLAG_t (1<<7)
-#define FLAG_s (1<<8)
-#define FLAG_p (1<<9)
-#define FLAG_O (1<<10)
-#define FLAG_o (1<<11)
-#define FLAG_n (1<<12)
-#define FLAG_M (1<<13)
-#define FLAG_l (1<<14)
-#define FLAG_f (1<<15)
-#define FLAG_e (1<<16)
-#define FLAG_d (1<<17)
-#define FLAG_A (1<<18)
-#define FLAG_a (1<<19)
-#define FLAG_P (1<<20)
-#define FLAG_k (1<<21)
+#define FLAG_Z (1LL<<0)
+#define FLAG_w (1LL<<1)
+#define FLAG_G (1LL<<2)
+#define FLAG_g (1LL<<3)
+#define FLAG_U (1LL<<4)
+#define FLAG_u (1LL<<5)
+#define FLAG_T (1LL<<6)
+#define FLAG_t (1LL<<7)
+#define FLAG_s (1LL<<8)
+#define FLAG_p (1LL<<9)
+#define FLAG_O (1LL<<10)
+#define FLAG_o (1LL<<11)
+#define FLAG_n (1LL<<12)
+#define FLAG_M (1LL<<13)
+#define FLAG_l (1LL<<14)
+#define FLAG_f (1LL<<15)
+#define FLAG_e (1LL<<16)
+#define FLAG_d (1LL<<17)
+#define FLAG_A (1LL<<18)
+#define FLAG_a (1LL<<19)
+#define FLAG_P (1LL<<20)
+#define FLAG_k (1LL<<21)
 #endif
 
 #ifdef FOR_pwd
@@ -5990,8 +6175,8 @@
 #ifndef TT
 #define TT this.pwd
 #endif
-#define FLAG_P (1<<0)
-#define FLAG_L (1<<1)
+#define FLAG_P (1LL<<0)
+#define FLAG_L (1LL<<1)
 #endif
 
 #ifdef FOR_pwdx
@@ -6052,11 +6237,29 @@
 #ifndef TT
 #define TT this.readlink
 #endif
-#define FLAG_f (1<<0)
-#define FLAG_e (1<<1)
-#define FLAG_m (1<<2)
-#define FLAG_q (1<<3)
-#define FLAG_n (1<<4)
+#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 (1LL<<0)
+#define FLAG_q (1LL<<1)
+#define FLAG_m (1LL<<2)
+#define FLAG_e (1LL<<3)
+#define FLAG_P (1LL<<4)
+#define FLAG_L (1LL<<5)
+#define FLAG_s (1LL<<6)
+#define FLAG_R (1LL<<7)
+#define FLAG_relative_base (1LL<<8)
 #endif
 
 #ifdef FOR_reboot
@@ -6119,11 +6322,11 @@
 #ifndef TT
 #define TT this.rm
 #endif
-#define FLAG_v (1<<0)
-#define FLAG_r (1<<1)
-#define FLAG_R (1<<2)
-#define FLAG_i (1<<3)
-#define FLAG_f (1<<4)
+#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_rmdir
@@ -6131,8 +6334,8 @@
 #ifndef TT
 #define TT this.rmdir
 #endif
-#define FLAG_p (1<<0)
-#define FLAG_ignore_fail_on_non_empty (1<<1)
+#define FLAG_p (1LL<<0)
+#define FLAG_ignore_fail_on_non_empty (1LL<<1)
 #endif
 
 #ifdef FOR_rmmod
@@ -6183,16 +6386,17 @@
 #ifndef TT
 #define TT this.sed
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_z (1<<1)
-#define FLAG_r (1<<2)
-#define FLAG_E (1<<3)
-#define FLAG_n (1<<4)
-#define FLAG_i (1<<5)
-#define FLAG_f (1<<6)
-#define FLAG_e (1<<7)
-#define FLAG_version (1<<8)
-#define FLAG_help (1<<9)
+#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_sendevent
@@ -6207,9 +6411,9 @@
 #ifndef TT
 #define TT this.seq
 #endif
-#define FLAG_w (1<<0)
-#define FLAG_s (1<<1)
-#define FLAG_f (1<<2)
+#define FLAG_w (1LL<<0)
+#define FLAG_s (1LL<<1)
+#define FLAG_f (1LL<<2)
 #endif
 
 #ifdef FOR_set
@@ -6242,9 +6446,9 @@
 #ifndef TT
 #define TT this.setsid
 #endif
-#define FLAG_d (1<<0)
-#define FLAG_c (1<<1)
-#define FLAG_w (1<<2)
+#define FLAG_d (1LL<<0)
+#define FLAG_c (1LL<<1)
+#define FLAG_w (1LL<<2)
 #endif
 
 #ifdef FOR_sh
@@ -6291,6 +6495,16 @@
 #define FLAG_z (FORCED_FLAG<<6)
 #endif
 
+#ifdef FOR_shuf
+#define CLEANUP_shuf
+#ifndef TT
+#define TT this.shuf
+#endif
+#define FLAG_n (FORCED_FLAG<<0)
+#define FLAG_e (FORCED_FLAG<<1)
+#define FLAG_z (FORCED_FLAG<<2)
+#endif
+
 #ifdef FOR_skeleton
 #define CLEANUP_skeleton
 #ifndef TT
@@ -6301,9 +6515,12 @@
 #define FLAG_c (FORCED_FLAG<<2)
 #define FLAG_d (FORCED_FLAG<<3)
 #define FLAG_e (FORCED_FLAG<<4)
-#define FLAG_also (FORCED_FLAG<<5)
-#define FLAG_blubber (FORCED_FLAG<<6)
-#define FLAG_walrus (FORCED_FLAG<<7)
+#define FLAG_f (FORCED_FLAG<<5)
+#define FLAG_g (FORCED_FLAG<<6)
+#define FLAG_h (FORCED_FLAG<<7)
+#define FLAG_also (FORCED_FLAG<<8)
+#define FLAG_blubber (FORCED_FLAG<<9)
+#define FLAG_walrus (FORCED_FLAG<<10)
 #endif
 
 #ifdef FOR_skeleton_alias
@@ -6346,26 +6563,27 @@
 #ifndef TT
 #define TT this.sort
 #endif
-#define FLAG_n (1<<0)
-#define FLAG_u (1<<1)
-#define FLAG_r (1<<2)
-#define FLAG_i (1<<3)
-#define FLAG_f (1<<4)
-#define FLAG_d (1<<5)
-#define FLAG_z (1<<6)
-#define FLAG_s (1<<7)
-#define FLAG_c (1<<8)
-#define FLAG_M (1<<9)
-#define FLAG_b (1<<10)
-#define FLAG_V (1<<11)
-#define FLAG_x (1<<12)
-#define FLAG_t (1<<13)
-#define FLAG_k (1<<14)
-#define FLAG_o (1<<15)
-#define FLAG_m (1<<16)
-#define FLAG_T (1<<17)
-#define FLAG_S (1<<18)
-#define FLAG_g (1<<19)
+#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 (1LL<<20)
 #endif
 
 #ifdef FOR_source
@@ -6391,10 +6609,10 @@
 #ifndef TT
 #define TT this.stat
 #endif
-#define FLAG_t (1<<0)
-#define FLAG_L (1<<1)
-#define FLAG_f (1<<2)
-#define FLAG_c (1<<3)
+#define FLAG_t (1LL<<0)
+#define FLAG_L (1LL<<1)
+#define FLAG_f (1LL<<2)
+#define FLAG_c (1LL<<3)
 #endif
 
 #ifdef FOR_strace
@@ -6456,6 +6674,8 @@
 #ifndef TT
 #define TT this.swapoff
 #endif
+#define FLAG_v (FORCED_FLAG<<0)
+#define FLAG_a (FORCED_FLAG<<1)
 #endif
 
 #ifdef FOR_swapon
@@ -6531,11 +6751,11 @@
 #ifndef TT
 #define TT this.tail
 #endif
-#define FLAG_n (1<<0)
-#define FLAG_c (1<<1)
-#define FLAG_s (1<<2)
-#define FLAG_F (1<<3)
-#define FLAG_f (1<<4)
+#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_tar
@@ -6543,41 +6763,54 @@
 #ifndef TT
 #define TT this.tar
 #endif
-#define FLAG_a (1<<0)
-#define FLAG_f (1<<1)
-#define FLAG_C (1<<2)
-#define FLAG_T (1<<3)
-#define FLAG_X (1<<4)
-#define FLAG_m (1<<5)
-#define FLAG_P (1<<6)
-#define FLAG_O (1<<7)
-#define FLAG_S (1<<8)
-#define FLAG_z (1<<9)
-#define FLAG_j (1<<10)
-#define FLAG_J (1<<11)
-#define FLAG_I (1<<12)
-#define FLAG_v (1<<13)
-#define FLAG_t (1<<14)
-#define FLAG_x (1<<15)
-#define FLAG_h (1<<16)
-#define FLAG_c (1<<17)
-#define FLAG_k (1<<18)
-#define FLAG_p (1<<19)
-#define FLAG_o (1<<20)
-#define FLAG_to_command (1<<21)
-#define FLAG_owner (1<<22)
-#define FLAG_group (1<<23)
-#define FLAG_mtime (1<<24)
-#define FLAG_mode (1<<25)
-#define FLAG_exclude (1<<26)
-#define FLAG_overwrite (1<<27)
-#define FLAG_no_same_permissions (1<<28)
-#define FLAG_numeric_owner (1<<29)
-#define FLAG_no_recursion (1<<30)
-#define FLAG_full_time (1LL<<31)
-#define FLAG_restrict (1LL<<32)
-#define FLAG_selinux (1LL<<33)
-#define FLAG_strip_components (1LL<<34)
+#define FLAG_s (1LL<<0)
+#define FLAG_a (1LL<<1)
+#define FLAG_f (1LL<<2)
+#define FLAG_C (1LL<<3)
+#define FLAG_I (1LL<<4)
+#define FLAG_T (1LL<<5)
+#define FLAG_X (1LL<<6)
+#define FLAG_m (1LL<<7)
+#define FLAG_P (1LL<<8)
+#define FLAG_O (1LL<<9)
+#define FLAG_S (1LL<<10)
+#define FLAG_z (1LL<<11)
+#define FLAG_j (1LL<<12)
+#define FLAG_J (1LL<<13)
+#define FLAG_v (1LL<<14)
+#define FLAG_t (1LL<<15)
+#define FLAG_x (1LL<<16)
+#define FLAG_h (1LL<<17)
+#define FLAG_c (1LL<<18)
+#define FLAG_k (1LL<<19)
+#define FLAG_p (1LL<<20)
+#define FLAG_o (1LL<<21)
+#define FLAG_xform (1LL<<22)
+#define FLAG_strip (1LL<<23)
+#define FLAG_to_command (1LL<<24)
+#define FLAG_owner (1LL<<25)
+#define FLAG_group (1LL<<26)
+#define FLAG_mtime (1LL<<27)
+#define FLAG_mode (1LL<<28)
+#define FLAG_sort (1LL<<29)
+#define FLAG_exclude (1LL<<30)
+#define FLAG_overwrite (1LL<<31)
+#define FLAG_no_same_permissions (1LL<<32)
+#define FLAG_numeric_owner (1LL<<33)
+#define FLAG_null (1LL<<34)
+#define FLAG_no_recursion (1LL<<35)
+#define FLAG_full_time (1LL<<36)
+#define FLAG_restrict (1LL<<37)
+#define FLAG_selinux (1LL<<38)
+#define FLAG_show_transformed_names (1LL<<39)
+#define FLAG_wildcards_match_slash (1LL<<40)
+#define FLAG_no_wildcards_match_slash (1LL<<41)
+#define FLAG_wildcards (1LL<<42)
+#define FLAG_no_wildcards (1LL<<43)
+#define FLAG_anchored (1LL<<44)
+#define FLAG_no_anchored (1LL<<45)
+#define FLAG_ignore_case (1LL<<46)
+#define FLAG_no_ignore_case (1LL<<47)
 #endif
 
 #ifdef FOR_taskset
@@ -6599,8 +6832,8 @@
 #define FLAG_h (FORCED_FLAG<<2)
 #define FLAG_l (FORCED_FLAG<<3)
 #define FLAG_u (FORCED_FLAG<<4)
-#define FLAG_b (FORCED_FLAG<<5)
-#define FLAG_C (FORCED_FLAG<<6)
+#define FLAG_C (FORCED_FLAG<<5)
+#define FLAG_b (FORCED_FLAG<<6)
 #define FLAG_c (FORCED_FLAG<<7)
 #endif
 
@@ -6609,8 +6842,8 @@
 #ifndef TT
 #define TT this.tee
 #endif
-#define FLAG_a (1<<0)
-#define FLAG_i (1<<1)
+#define FLAG_a (1LL<<0)
+#define FLAG_i (1LL<<1)
 #endif
 
 #ifdef FOR_telnet
@@ -6680,11 +6913,12 @@
 #ifndef TT
 #define TT this.timeout
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_k (1<<1)
-#define FLAG_v (1<<2)
-#define FLAG_preserve_status (1<<3)
-#define FLAG_foreground (1<<4)
+#define FLAG_i (1LL<<0)
+#define FLAG_s (1LL<<1)
+#define FLAG_k (1LL<<2)
+#define FLAG_v (1LL<<3)
+#define FLAG_preserve_status (1LL<<4)
+#define FLAG_foreground (1LL<<5)
 #endif
 
 #ifdef FOR_top
@@ -6712,14 +6946,14 @@
 #ifndef TT
 #define TT this.touch
 #endif
-#define FLAG_h (1<<0)
-#define FLAG_t (1<<1)
-#define FLAG_r (1<<2)
-#define FLAG_m (1<<3)
-#define FLAG_f (1<<4)
-#define FLAG_d (1<<5)
-#define FLAG_c (1<<6)
-#define FLAG_a (1<<7)
+#define FLAG_h (1LL<<0)
+#define FLAG_t (1LL<<1)
+#define FLAG_r (1LL<<2)
+#define FLAG_m (1LL<<3)
+#define FLAG_f (1LL<<4)
+#define FLAG_d (1LL<<5)
+#define FLAG_c (1LL<<6)
+#define FLAG_a (1LL<<7)
 #endif
 
 #ifdef FOR_toybox
@@ -6734,10 +6968,10 @@
 #ifndef TT
 #define TT this.tr
 #endif
-#define FLAG_d (1<<0)
-#define FLAG_s (1<<1)
-#define FLAG_c (1<<2)
-#define FLAG_C (1<<3)
+#define FLAG_d (1LL<<0)
+#define FLAG_s (1LL<<1)
+#define FLAG_c (1LL<<2)
+#define FLAG_C (1LL<<3)
 #endif
 
 #ifdef FOR_traceroute
@@ -6779,8 +7013,8 @@
 #ifndef TT
 #define TT this.truncate
 #endif
-#define FLAG_c (1<<0)
-#define FLAG_s (1<<1)
+#define FLAG_c (1LL<<0)
+#define FLAG_s (1LL<<1)
 #endif
 
 #ifdef FOR_tty
@@ -6863,13 +7097,14 @@
 #ifndef TT
 #define TT this.uname
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_n (1<<1)
-#define FLAG_r (1<<2)
-#define FLAG_v (1<<3)
-#define FLAG_m (1<<4)
-#define FLAG_o (1<<5)
-#define FLAG_a (1<<6)
+#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_unicode
@@ -6884,14 +7119,14 @@
 #ifndef TT
 #define TT this.uniq
 #endif
-#define FLAG_u (1<<0)
-#define FLAG_d (1<<1)
-#define FLAG_c (1<<2)
-#define FLAG_i (1<<3)
-#define FLAG_z (1<<4)
-#define FLAG_w (1<<5)
-#define FLAG_s (1<<6)
-#define FLAG_f (1<<7)
+#define FLAG_u (1LL<<0)
+#define FLAG_d (1LL<<1)
+#define FLAG_c (1LL<<2)
+#define FLAG_i (1LL<<3)
+#define FLAG_z (1LL<<4)
+#define FLAG_w (1LL<<5)
+#define FLAG_s (1LL<<6)
+#define FLAG_f (1LL<<7)
 #endif
 
 #ifdef FOR_unix2dos
@@ -6929,8 +7164,10 @@
 #define FLAG_n (FORCED_FLAG<<3)
 #define FLAG_m (FORCED_FLAG<<4)
 #define FLAG_i (FORCED_FLAG<<5)
-#define FLAG_r (FORCED_FLAG<<6)
-#define FLAG_f (FORCED_FLAG<<7)
+#define FLAG_C (FORCED_FLAG<<6)
+#define FLAG_r (FORCED_FLAG<<7)
+#define FLAG_f (FORCED_FLAG<<8)
+#define FLAG_a (FORCED_FLAG<<9)
 #endif
 
 #ifdef FOR_uptime
@@ -7061,10 +7298,10 @@
 #ifndef TT
 #define TT this.wc
 #endif
-#define FLAG_l (1<<0)
-#define FLAG_w (1<<1)
-#define FLAG_c (1<<2)
-#define FLAG_m (1<<3)
+#define FLAG_l (1LL<<0)
+#define FLAG_w (1LL<<1)
+#define FLAG_c (1LL<<2)
+#define FLAG_m (1LL<<3)
 #endif
 
 #ifdef FOR_wget
@@ -7083,7 +7320,7 @@
 #ifndef TT
 #define TT this.which
 #endif
-#define FLAG_a (1<<0)
+#define FLAG_a (1LL<<0)
 #endif
 
 #ifdef FOR_who
@@ -7099,15 +7336,15 @@
 #ifndef TT
 #define TT this.xargs
 #endif
-#define FLAG_0 (1<<0)
-#define FLAG_s (1<<1)
-#define FLAG_n (1<<2)
-#define FLAG_r (1<<3)
-#define FLAG_t (1<<4)
-#define FLAG_p (1<<5)
-#define FLAG_o (1<<6)
-#define FLAG_P (1<<7)
-#define FLAG_E (1<<8)
+#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
 
 #ifdef FOR_xxd
@@ -7115,14 +7352,15 @@
 #ifndef TT
 #define TT this.xxd
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_r (1<<1)
-#define FLAG_p (1<<2)
-#define FLAG_i (1<<3)
-#define FLAG_g (1<<4)
-#define FLAG_o (1<<5)
-#define FLAG_l (1<<6)
-#define FLAG_c (1<<7)
+#define FLAG_s (1LL<<0)
+#define FLAG_r (1LL<<1)
+#define FLAG_p (1LL<<2)
+#define FLAG_i (1LL<<3)
+#define FLAG_e (1LL<<4)
+#define FLAG_g (1LL<<5)
+#define FLAG_o (1LL<<6)
+#define FLAG_l (1LL<<7)
+#define FLAG_c (1LL<<8)
 #endif
 
 #ifdef FOR_xzcat
@@ -7144,18 +7382,19 @@
 #ifndef TT
 #define TT this.zcat
 #endif
-#define FLAG_9 (1<<0)
-#define FLAG_8 (1<<1)
-#define FLAG_7 (1<<2)
-#define FLAG_6 (1<<3)
-#define FLAG_5 (1<<4)
-#define FLAG_4 (1<<5)
-#define FLAG_3 (1<<6)
-#define FLAG_2 (1<<7)
-#define FLAG_1 (1<<8)
-#define FLAG_k (1<<9)
-#define FLAG_f (1<<10)
-#define FLAG_d (1<<11)
-#define FLAG_c (1<<12)
+#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)
 #endif
 
diff --git a/android/linux/generated/globals.h b/android/linux/generated/globals.h
index 403077b..2b646d0 100644
--- a/android/linux/generated/globals.h
+++ b/android/linux/generated/globals.h
@@ -2,6 +2,8 @@
 
 struct log_data {
   char *t, *p;
+
+  int pri;
 };
 
 // toys/example/demo_number.c
@@ -25,7 +27,7 @@
       long c;
       struct arg_list *d;
       long e;
-      char *also, *blubber;
+      char *f, *g, *h, *also, *blubber;
     } s;
     struct {
       long b;
@@ -99,9 +101,8 @@
 // toys/lsb/mount.c
 
 struct mount_data {
-  struct arg_list *optlist;
-  char *type;
-  char *bigO;
+  struct arg_list *o;
+  char *t, *O;
 
   unsigned long flags;
   char *opts;
@@ -213,6 +214,22 @@
   char *u;
 };
 
+// toys/net/wget.c
+
+struct wget_data {
+  char *p, *O;
+  long max_redirect;
+
+  int sock, https;
+  char *url;
+#if CFG_WGET_LIBTLS
+  struct tls *tls;
+#elif CFG_TOYBOX_LIBCRYPTO
+  struct ssl_ctx_st *ctx;
+  struct ssl_st *ssl;
+#endif
+};
+
 // toys/other/acpi.c
 
 struct acpi_data {
@@ -224,6 +241,7 @@
 
 struct base64_data {
   long w;
+
   unsigned total;
   unsigned n;  // number of bits used in encoding. 5 for base32, 6 for base64
   unsigned align;  // number of bits to align to
@@ -239,6 +257,7 @@
 
 struct blkid_data {
   struct arg_list *s;
+  char *o;
 };
 
 // toys/other/blockdev.c
@@ -268,7 +287,7 @@
 // toys/other/fmt.c
 
 struct fmt_data {
-  int width;
+  long width;
 
   int level, pos;
 };
@@ -343,7 +362,7 @@
 
 struct lsusb_data {
   char *i;
-  long n;
+  long x, n;
 
   void *ids, *class;
   int count;
@@ -384,10 +403,18 @@
   int count;
 };
 
+// toys/other/nbd_client.c
+
+struct nbd_client_data {
+  long b;
+
+  int nbd;
+};
+
 // toys/other/nsenter.c
 
 struct nsenter_data {
-  char *Uupnmi[6];
+  char *UupnmiC[6];
   long t;
 };
 
@@ -419,6 +446,12 @@
   int bits, endian, shnum, shentsize, phentsize;
 };
 
+// toys/other/readlink.c
+
+struct readlink_data {
+  char *R, *relative_base;
+};
+
 // toys/other/reboot.c
 
 struct reboot_data {
@@ -451,6 +484,15 @@
   long o, n, s;
 };
 
+// toys/other/shuf.c
+
+struct shuf_data {
+  long n;
+
+  char **lines;
+  long count;
+};
+
 // toys/other/stat.c
 
 struct stat_data {
@@ -489,11 +531,9 @@
 struct timeout_data {
   char *s, *k;
 
-  int nextsig;
-  pid_t pid;
-  struct timespec kts;
-  struct itimerspec its;
-  timer_t timer;
+  struct pollfd pfd;
+  sigjmp_buf sj;
+  int fds[2], pid;
 };
 
 // toys/other/truncate.c
@@ -616,8 +656,7 @@
 
 struct dd_data {
   int show_xfer, show_records;
-  unsigned long long bytes, c_count, in_full, in_part, out_full, out_part;
-  struct timeval start;
+  unsigned long long bytes, in_full, in_part, out_full, out_part, start;
   struct {
     char *name;
     int fd;
@@ -667,13 +706,20 @@
 // toys/pending/diff.c
 
 struct diff_data {
-  long ct;
-  char *start;
-  struct arg_list *L_list;
+  long U;
+  struct arg_list *L;
+  char *F, *S, *new_line_format, *old_line_format, *unchanged_line_format;
 
-  int dir_num, size, is_binary, status, change, len[2];
-  int *offset[2];
+  int dir_num, size, is_binary, differ, change, len[2], *offset[2];
   struct stat st[2];
+  struct {
+    char **list;
+    int nr_elm;
+  } dir[2];
+  struct {
+    FILE *fp;
+    int len;
+  } file[2];
 };
 
 // toys/pending/dumpleases.c
@@ -745,6 +791,13 @@
   struct termios termios;
 };
 
+// toys/pending/git.c
+
+struct git_data {
+  char *url, *name; //git repo remote url and init directory name
+  struct IndexV2 *i; //git creates a index for each pack file, git clone just needs one index for the received pack file
+};
+
 // toys/pending/groupadd.c
 
 struct groupadd_data {
@@ -890,7 +943,7 @@
   long long SECONDS;
   char *isexec, *wcpat;
   unsigned options, jobcnt, LINENO;
-  int hfd, pid, bangpid, varslen, srclvl, recursion;
+  int hfd, pid, bangpid, srclvl, recursion;
 
   // Callable function array
   struct sh_function {
@@ -916,11 +969,11 @@
       long flags;
       char *str;
     } *vars;
-    long varslen, shift;
+    long varslen, varscap, shift, oldlineno;
 
     struct sh_function *func; // TODO wire this up
     struct sh_pipeline *pl;
-    char *ifs;
+    char *ifs, *omnom;
     struct sh_arg arg;
     struct arg_list *delete;
 
@@ -998,11 +1051,8 @@
 // toys/pending/tcpsvd.c
 
 struct tcpsvd_data {
-  char *name;
-  char *user;
-  long bn;
-  char *nmsg;
-  long cn;
+  char *l, *u, *C;
+  long b, c;
 
   int maxc;
   int count_all;
@@ -1100,6 +1150,8 @@
 
 struct vi_data {
   char *s;
+
+  char *filename;
   int vi_mode, tabstop, list;
   int cur_col, cur_row, scr_row;
   int drawn_row, drawn_col;
@@ -1119,13 +1171,9 @@
     char* data;
   } yank;
 
-  int modified;
   size_t filesize;
 // mem_block contains RO data that is either original file as mmap
 // or heap allocated inserted data
-//
-//
-//
   struct block_list {
     struct block_list *next, *prev;
     struct mem_block {
@@ -1156,22 +1204,6 @@
   } *slices;
 };
 
-// toys/pending/wget.c
-
-struct wget_data {
-  char *p, *O;
-  long max_redirect;
-
-  int sock, https;
-  char *url;
-#if CFG_WGET_LIBTLS
-  struct tls *tls;
-#elif CFG_WGET_OPENSSL
-  struct ssl_ctx_st *ctx;
-  struct ssl_st *ssl;
-#endif
-};
-
 // toys/posix/basename.c
 
 struct basename_data {
@@ -1239,7 +1271,7 @@
 // toys/posix/cpio.c
 
 struct cpio_data {
-  char *F, *H;
+  char *F, *H, *R;
 };
 
 // toys/posix/cut.c
@@ -1320,8 +1352,8 @@
 
   char *purple, *cyan, *red, *green, *grey;
   struct double_list *reg;
-  char indelim, outdelim;
-  int found, tried;
+  int found, tried, delim;
+  struct arg_list *fixed[256];
 };
 
 // toys/posix/head.c
@@ -1363,14 +1395,15 @@
 
 struct logger_data {
   char *p, *t;
+
+  int priority;
 };
 
 // toys/posix/ls.c
 
 struct ls_data {
-  long w;
-  long l;
-  char *color;
+  long w, l;
+  char *color, *sort;
 
   struct dirtree *files, *singledir;
   unsigned screen_width;
@@ -1465,7 +1498,10 @@
     } pgrep;
   };
 
-  struct ptr_len gg, GG, pp, PP, ss, tt, uu, UU;
+  struct ps_ptr_len {
+    void *ptr;
+    long len;
+  } gg, GG, pp, PP, ss, tt, uu, UU;
   struct dirtree *threadparent;
   unsigned width, height, scroll;
   dev_t tty;
@@ -1491,12 +1527,12 @@
   // processed pattern list
   struct double_list *pattern;
 
-  char *nextline, *remember;
+  char *nextline, *remember, *tarxform;
   void *restart, *lastregex;
   long nextlen, rememberlen, count;
   int fdout, noeol;
-  unsigned xx;
-  char delim;
+  unsigned xx, tarxlen, xflags;
+  char delim, xftype;
 };
 
 // toys/posix/sort.c
@@ -1537,32 +1573,31 @@
   struct {
     char *path;
     int fd;
-    dev_t dev;
-    ino_t ino;
+    struct dev_ino di;
   } *F;
 };
 
 // toys/posix/tar.c
 
 struct tar_data {
-  char *f, *C;
-  struct arg_list *T, *X;
-  char *I, *to_command, *owner, *group, *mtime, *mode;
+  char *f, *C, *I;
+  struct arg_list *T, *X, *xform;
+  long strip;
+  char *to_command, *owner, *group, *mtime, *mode, *sort;
   struct arg_list *exclude;
-  long strip_components;
 
   struct double_list *incl, *excl, *seen;
   struct string_list *dirs;
-  char *cwd;
-  int fd, ouid, ggid, hlc, warn, adev, aino, sparselen, pid;
+  char *cwd, **xfsed;
+  int fd, ouid, ggid, hlc, warn, sparselen, pid, xfpipe[2];
+  struct dev_ino archive_di;
   long long *sparse;
   time_t mtt;
 
   // hardlinks seen so far (hlc many)
   struct {
     char *arg;
-    ino_t ino;
-    dev_t dev;
+    struct dev_ino di;
   } *hlx;
 
   // Parsed information about a tar header.
@@ -1654,6 +1689,7 @@
 	struct ping_data ping;
 	struct sntp_data sntp;
 	struct tunctl_data tunctl;
+	struct wget_data wget;
 	struct acpi_data acpi;
 	struct base64_data base64;
 	struct blkdiscard_data blkdiscard;
@@ -1677,16 +1713,19 @@
 	struct mkpasswd_data mkpasswd;
 	struct mkswap_data mkswap;
 	struct modinfo_data modinfo;
+	struct nbd_client_data nbd_client;
 	struct nsenter_data nsenter;
 	struct oneit_data oneit;
 	struct openvt_data openvt;
 	struct pwgen_data pwgen;
 	struct readelf_data readelf;
+	struct readlink_data readlink;
 	struct reboot_data reboot;
 	struct rtcwake_data rtcwake;
 	struct setfattr_data setfattr;
 	struct sha3sum_data sha3sum;
 	struct shred_data shred;
+	struct shuf_data shuf;
 	struct stat_data stat;
 	struct swapon_data swapon;
 	struct switch_root_data switch_root;
@@ -1718,6 +1757,7 @@
 	struct getfattr_data getfattr;
 	struct getopt_data getopt;
 	struct getty_data getty;
+	struct git_data git;
 	struct groupadd_data groupadd;
 	struct hexdump_data hexdump;
 	struct ip_data ip;
@@ -1745,7 +1785,6 @@
 	struct traceroute_data traceroute;
 	struct useradd_data useradd;
 	struct vi_data vi;
-	struct wget_data wget;
 	struct basename_data basename;
 	struct cal_data cal;
 	struct chgrp_data chgrp;
diff --git a/android/linux/generated/help.h b/android/linux/generated/help.h
index 30c24e9..aef8828 100644
--- a/android/linux/generated/help.h
+++ b/android/linux/generated/help.h
@@ -104,15 +104,19 @@
 
 #define HELP_zcat "usage: zcat [FILE...]\n\nDecompress files to stdout. Like `gzip -dc`.\n\n-f	Force: allow read from tty"
 
-#define HELP_gunzip "usage: gunzip [-cfk] [FILE...]\n\nDecompress files. With no files, decompresses stdin to stdout.\nOn success, the input files are removed and replaced by new\nfiles without the .gz suffix.\n\n-c	Output to stdout (act as zcat)\n-f	Force: allow read from tty\n-k	Keep input files (default is to remove)"
+#define HELP_gunzip "usage: gunzip [-cfkt] [FILE...]\n\nDecompress files. With no files, decompresses stdin to stdout.\nOn success, the input files are removed and replaced by new\nfiles without the .gz suffix.\n\n-c	Output to stdout (act as zcat)\n-f	Force: allow read from tty\n-k	Keep input files (default is to remove)\n-t	Test integrity"
 
-#define HELP_gzip "usage: gzip [-19cdfk] [FILE...]\n\nCompress files. With no files, compresses stdin to stdout.\nOn success, the input files are removed and replaced by new\nfiles with the .gz suffix.\n\n-c	Output to stdout\n-d	Decompress (act as gunzip)\n-f	Force: allow overwrite of output file\n-k	Keep input files (default is to remove)\n-#	Compression level 1-9 (1:fastest, 6:default, 9:best)"
+#define HELP_gzip "usage: gzip [-19cdfkt] [FILE...]\n\nCompress files. With no files, compresses stdin to stdout.\nOn success, the input files are removed and replaced by new\nfiles with the .gz suffix.\n\n-c	Output to stdout\n-d	Decompress (act as gunzip)\n-f	Force: allow overwrite of output file\n-k	Keep input files (default is to remove)\n-t	Test integrity\n-#	Compression level 1-9 (1:fastest, 6:default, 9:best)"
 
 #define HELP_dmesg "usage: dmesg [-Cc] [-r|-t|-T] [-n LEVEL] [-s SIZE] [-w]\n\nPrint or control the kernel ring buffer.\n\n-C	Clear ring buffer without printing\n-c	Clear ring buffer after printing\n-n	Set kernel logging LEVEL (1-9)\n-r	Raw output (with <level markers>)\n-S	Use syslog(2) rather than /dev/kmsg\n-s	Show the last SIZE many bytes\n-T	Human readable timestamps\n-t	Don't print timestamps\n-w	Keep waiting for more output (aka --follow)"
 
+#define HELP_wget_libtls "Enable HTTPS support for wget by linking to LibTLS.\nSupports using libtls, libretls or libtls-bearssl.\n\nUse TOYBOX_LIBCRYPTO to enable HTTPS support via OpenSSL."
+
+#define HELP_wget "usage: wget [OPTIONS]... [URL]\n    --max-redirect          maximum redirections allowed\n-d, --debug                 print lots of debugging information\n-O, --output-document=FILE  specify output filename\n-p, --post-data=DATA        send data in body of POST request\n\nexamples:\n  wget http://www.example.com"
+
 #define HELP_tunctl "usage: tunctl [-dtT] [-u USER] NAME\n\nCreate and delete tun/tap virtual ethernet devices.\n\n-T	Use tap (ethernet frames) instead of tun (ip packets)\n-d	Delete tun/tap device\n-t	Create tun/tap device\n-u	Set owner (user who can read/write device without root access)"
 
-#define HELP_sntp "usage: sntp [-saSdDq] [-r SHIFT] [-mM[ADDRESS]] [-p PORT] [SERVER]\n\nSimple Network Time Protocol client. Query SERVER and display time.\n\n-p	Use PORT (default 123)\n-s	Set system clock suddenly\n-a	Adjust system clock gradually\n-S	Serve time instead of querying (bind to SERVER address if specified)\n-m	Wait for updates from multicast ADDRESS (RFC 4330 default 224.0.1.1)\n-M	Multicast server on ADDRESS (default 224.0.0.1)\n-t	TTL (multicast only, default 1)\n-d	Daemonize (run in background re-querying )\n-D	Daemonize but stay in foreground: re-query time every 1000 seconds\n-r	Retry shift (every 1<<SHIFT seconds)\n-q	Quiet (don't display time)"
+#define HELP_sntp "usage: sntp [-saSdDq] [-r SHIFT] [-mM[ADDRESS]] [-p PORT] [SERVER]\n\nSimple Network Time Protocol client. Query SERVER and display time.\n\n-p	Use PORT (default 123)\n-s	Set system clock suddenly\n-a	Adjust system clock gradually\n-S	Serve time instead of querying (bind to SERVER address if specified)\n-m	Wait for updates from multicast ADDRESS (RFC 4330 suggests 224.0.1.1)\n-M	Multicast server on ADDRESS (RFC 4330 suggests 224.0.1.1)\n-t	TTL (multicast only, default 1)\n-d	Daemonize (run in background re-querying)\n-D	Daemonize but stay in foreground: re-query time every 1000 seconds\n-r	Retry shift (every 1<<SHIFT seconds)\n-q	Quiet (don't display time)"
 
 #define HELP_rfkill "usage: rfkill COMMAND [DEVICE]\n\nEnable/disable wireless devices.\n\nCommands:\nlist [DEVICE]   List current state\nblock DEVICE    Disable device\nunblock DEVICE  Enable device\n\nDEVICE is an index number, or one of:\nall, wlan(wifi), bluetooth, uwb(ultrawideband), wimax, wwan, gps, fm."
 
@@ -120,14 +124,14 @@
 
 #define HELP_netstat "usage: netstat [-pWrxwutneal]\n\nDisplay networking information. Default is netstat -tuwx\n\n-r	Routing table\n-a	All sockets (not just connected)\n-l	Listening server sockets\n-t	TCP sockets\n-u	UDP sockets\n-w	Raw sockets\n-x	Unix sockets\n-e	Extended info\n-n	Don't resolve names\n-W	Wide display\n-p	Show PID/program name of sockets"
 
-#define HELP_netcat_listen "usage: netcat [-tElL]\n\n-l	Listen for one incoming connection, then exit\n-L	Listen and background each incoming connection (server mode)\n-t	Allocate tty\n-E	Forward stderr\n\nWhen listening the COMMAND line is executed as a child process to handle\nan incoming connection. With no COMMAND -l forwards the connection\nto stdin/stdout. If no -p specified, -l prints the port it bound to and\nbackgrounds itself (returning immediately).\n\nFor a quick-and-dirty server, try something like:\nnetcat -s 127.0.0.1 -p 1234 -tL sh -l"
-
-#define HELP_netcat "usage: netcat [-46U] [-u] [-wpq #] [-s addr] {IPADDR PORTNUM|-f FILENAME|COMMAND...}\n\nForward stdin/stdout to a file or network connection.\n\n-4	Force IPv4\n-6	Force IPv6\n-f	Use FILENAME (ala /dev/ttyS0) instead of network\n-p	Local port number\n-q	Quit SECONDS after EOF on stdin, even if stdout hasn't closed yet\n-s	Local source address\n-u	Use UDP\n-U	Use a UNIX domain socket\n-w	SECONDS timeout to establish connection\n-W	SECONDS timeout for more data on an idle connection\n\nUse \"stty 115200 -F /dev/ttyS0 && stty raw -echo -ctlecho\" with\nnetcat -f to connect to a serial port."
+#define HELP_netcat "usage: netcat [-46ElLtUu] [-wpq #] [-s addr] {IPADDR PORTNUM|-f FILENAME|COMMAND...}\n\nForward stdin/stdout to a file or network connection.\n\n-4	Force IPv4\n-6	Force IPv6\n-E	Forward stderr\n-f	Use FILENAME (ala /dev/ttyS0) instead of network\n-l	Listen for one incoming connection, then exit\n-L	Listen and background each incoming connection (server mode)\n-n	No DNS lookup\n-p	Local port number\n-q	Quit SECONDS after EOF on stdin, even if stdout hasn't closed yet\n-s	Local source address\n-t	Allocate tty\n-u	Use UDP\n-U	Use a UNIX domain socket\n-w	SECONDS timeout to establish connection\n-W	SECONDS timeout for more data on an idle connection\n\nWhen listening the COMMAND line is executed as a child process to handle\nan incoming connection. With no COMMAND -l forwards the connection\nto stdin/stdout. If no -p specified, -l prints the port it bound to and\nbackgrounds itself (returning immediately).\n\nFor a quick-and-dirty server, try something like:\nnetcat -s 127.0.0.1 -p 1234 -tL sh -l\n\nOr use \"stty 115200 -F /dev/ttyS0 && stty raw -echo -ctlecho\" with\nnetcat -f to connect to a serial port."
 
 #define HELP_microcom "usage: microcom [-s SPEED] [-X] DEVICE\n\nSimple serial console.\n\n-s	Set baud rate to SPEED (default 115200)\n-X	Ignore ^@ (send break) and ^] (exit)"
 
 #define HELP_ifconfig "usage: ifconfig [-aS] [INTERFACE [ACTION...]]\n\nDisplay or configure network interface.\n\nWith no arguments, display active interfaces. First argument is interface\nto operate on, one argument by itself displays that interface.\n\n-a	All interfaces displayed, not just active ones\n-S	Short view, one line per interface\n\nStandard ACTIONs to perform on an INTERFACE:\n\nADDR[/MASK]        - set IPv4 address (1.2.3.4/5) and activate interface\nadd|del ADDR[/LEN] - add/remove IPv6 address (1111::8888/128)\nup|down            - activate or deactivate interface\n\nAdvanced ACTIONs (default values usually suffice):\n\ndefault          - remove IPv4 address\nnetmask ADDR     - set IPv4 netmask via 255.255.255.0 instead of /24\ntxqueuelen LEN   - number of buffered packets before output blocks\nmtu LEN          - size of outgoing packets (Maximum Transmission Unit)\nbroadcast ADDR   - Set broadcast address\npointopoint ADDR - PPP and PPPOE use this instead of \"route add default gw\"\nhw TYPE ADDR     - set hardware (mac) address (type = ether|infiniband)\nrename NEWNAME   - rename interface\n\nFlags you can set on an interface (or -remove by prefixing with -):\n\narp       - don't use Address Resolution Protocol to map LAN routes\npromisc   - don't discard packets that aren't to this LAN hardware address\nmulticast - force interface into multicast mode if the driver doesn't\nallmulti  - promisc for multicast packets"
 
+#define HELP_httpd "usage: httpd [-e STR] [DIR]\n\nServe contents of directory as static web pages.\n\n-e	Escape STR as URL, printing result and exiting.\n-d	Decode escaped STR, printing result and exiting.\n-v	Verbose"
+
 #define HELP_host "usage: host [-v] [-t TYPE] NAME [SERVER]\n\nLook up DNS records for NAME, either domain name or IPv4/IPv6 address to\nreverse lookup, from SERVER or default DNS server(s).\n\n-a	All records\n-t TYPE	Record TYPE (number or ANY A AAAA CNAME MX NS PTR SOA SRV TXT)\n-v	Verbose"
 
 #define HELP_ftpput "An ftpget that defaults to -s instead of -g"
@@ -136,7 +140,7 @@
 
 #define HELP_yes "usage: yes [args...]\n\nRepeatedly output line until killed. If no args, output 'y'."
 
-#define HELP_xxd "usage: xxd [-c n] [-g n] [-i] [-l n] [-o n] [-p] [-r] [-s n] [file]\n\nHexdump a file to stdout. If no file is listed, copy from stdin.\nFilename \"-\" is a synonym for stdin.\n\n-c n	Show n bytes per line (default 16)\n-g n	Group bytes by adding a ' ' every n bytes (default 2)\n-i	Output include file (CSV hex bytes, plus C header/footer if not stdin)\n-l n	Limit of n bytes before stopping (default is no limit)\n-o n	Add n to display offset\n-p	Plain hexdump (30 bytes/line, no grouping)\n-r	Reverse operation: turn a hexdump into a binary file\n-s n	Skip to offset n"
+#define HELP_xxd "usage: xxd [-eipr] [-cglos N] [file]\n\nHexdump a file to stdout. If no file is listed, copy from stdin.\nFilename \"-\" is a synonym for stdin.\n\n-c N	Show N bytes per line (default 16)\n-e	Little-endian\n-g N	Group bytes by adding a ' ' every N bytes (default 2)\n-i	Output include file (CSV hex bytes, plus C header/footer if not stdin)\n-l N	Limit of N bytes before stopping (default is no limit)\n-o N	Add N to display offset\n-p	Plain hexdump (30 bytes/line, no grouping. With -c 0 no wrap/group)\n-r	Reverse operation: turn a hexdump into a binary file\n-s N	Skip to offset N"
 
 #define HELP_which "usage: which [-a] filename ...\n\nSearch $PATH for executable files matching filename(s).\n\n-a	Show all matches"
 
@@ -160,7 +164,7 @@
 
 #define HELP_truncate "usage: truncate [-c] -s SIZE file...\n\nSet length of file(s), extending sparsely if necessary.\n\n-c	Don't create file if it doesn't exist\n-s	New size (with optional prefix and suffix)\n\nSIZE prefix: + add, - subtract, < shrink to, > expand to,\n             / multiple rounding down, % multiple rounding up\nSIZE suffix: k=1024, m=1024^2, g=1024^3, t=1024^4, p=1024^5, e=1024^6"
 
-#define HELP_timeout "usage: timeout [-k DURATION] [-s SIGNAL] DURATION COMMAND...\n\nRun command line as a child process, sending child a signal if the\ncommand doesn't exit soon enough.\n\nDURATION can be a decimal fraction. An optional suffix can be \"m\"\n(minutes), \"h\" (hours), \"d\" (days), or \"s\" (seconds, the default).\n\n-s	Send specified signal (default TERM)\n-k	Send KILL signal if child still running this long after first signal\n-v	Verbose\n--foreground       Don't create new process group\n--preserve-status  Exit with the child's exit status"
+#define HELP_timeout "usage: timeout [-i] [-k DURATION] [-s SIGNAL] DURATION COMMAND...\n\nRun command line as a child process, sending child a signal if the\ncommand doesn't exit soon enough.\n\nDURATION can be a decimal fraction. An optional suffix can be \"m\"\n(minutes), \"h\" (hours), \"d\" (days), or \"s\" (seconds, the default).\n\n-i	Only kill for inactivity (restart timeout when command produces output)\n-k	Send KILL signal if child still running this long after first signal\n-s	Send specified signal (default TERM)\n-v	Verbose\n--foreground       Don't create new process group\n--preserve-status  Exit with the child's exit status"
 
 #define HELP_taskset "usage: taskset [-ap] [mask] [PID | cmd [args...]]\n\nLaunch a new task which may only run on certain processors, or change\nthe processor affinity of an existing PID.\n\nMask is a hex string where each bit represents a processor the process\nis allowed to run on. PID without a mask displays existing affinity.\n\n-p	Set/get the affinity of given PID instead of a new command\n-a	Set/get the affinity of all threads of the PID"
 
@@ -174,10 +178,12 @@
 
 #define HELP_swapon "usage: swapon [-d] [-p priority] filename\n\nEnable swapping on a given device/file.\n\n-d	Discard freed SSD pages\n-p	Priority (highest priority areas allocated first)"
 
-#define HELP_swapoff "usage: swapoff swapregion\n\nDisable swapping on a given swapregion."
+#define HELP_swapoff "usage: swapoff FILE\n\nDisable swapping on a device or file."
 
 #define HELP_stat "usage: stat [-tfL] [-c FORMAT] FILE...\n\nDisplay status of files or filesystems.\n\n-c	Output specified FORMAT string instead of default\n-f	Display filesystem status instead of file status\n-L	Follow symlinks\n-t	terse (-c \"%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o\")\n	      (with -f = -c \"%n %i %l %t %s %S %b %f %a %c %d\")\n\nThe valid format escape sequences for files:\n%a  Access bits (octal) |%A  Access bits (flags)|%b  Size/512\n%B  Bytes per %b (512)  |%C  Security context   |%d  Device ID (dec)\n%D  Device ID (hex)     |%f  All mode bits (hex)|%F  File type\n%g  Group ID            |%G  Group name         |%h  Hard links\n%i  Inode               |%m  Mount point        |%n  Filename\n%N  Long filename       |%o  I/O block size     |%s  Size (bytes)\n%t  Devtype major (hex) |%T  Devtype minor (hex)|%u  User ID\n%U  User name           |%x  Access time        |%X  Access unix time\n%y  Modification time   |%Y  Mod unix time      |%z  Creation time\n%Z  Creation unix time\n\nThe valid format escape sequences for filesystems:\n%a  Available blocks    |%b  Total blocks       |%c  Total inodes\n%d  Free inodes         |%f  Free blocks        |%i  File system ID\n%l  Max filename length |%n  File name          |%s  Best transfer size\n%S  Actual block size   |%t  FS type (hex)      |%T  FS type (driver name)"
 
+#define HELP_shuf "usage: shuf [-ze] [-n COUNT] [FILE...]\n\nWrite lines of input to output in random order.\n\n-z	Input/output lines are NUL terminated.\n-n	Stop after COUNT many output lines.\n-e	Echo mode: arguments are inputs to shuffle, not files to read."
+
 #define HELP_shred "usage: shred [-fuxz] [-n COUNT] [-o OFFSET] [-s SIZE] FILE...\n\nSecurely delete a file by overwriting its contents with random data.\n\n-f		Force (chmod if necessary)\n-n COUNT	Random overwrite iterations (default 1)\n-o OFFSET	Start at OFFSET\n-s SIZE		Use SIZE instead of detecting file size\n-u		Unlink (actually delete file when done)\n-x		Use exact size (default without -s rounds up to next 4k)\n-z		Zero at end\n\nNote: data journaling filesystems render this command useless, you must\noverwrite all free space (fill up disk) to erase old data on those."
 
 #define HELP_sha3sum "usage: sha3sum [-S] [-a BITS] [FILE...]\n\nHash function du jour.\n\n-a	Produce a hash BITS long (default 224)\n-b	Brief (hash only, no filename)\n-S	Use SHAKE termination byte instead of SHA3 (ask FIPS why)"
@@ -196,9 +202,9 @@
 
 #define HELP_reboot "usage: reboot/halt/poweroff [-fn] [-d DELAY]\n\nRestart, halt, or power off the system.\n\n-d	Wait DELAY before proceeding (in seconds or m/h/d suffix: -d 1.5m = 90s)\n-f	Force reboot (don't signal init, reboot directly)\n-n	Don't sync filesystems before reboot"
 
-#define HELP_realpath "usage: realpath FILE...\n\nDisplay the canonical absolute pathname"
+#define HELP_realpath "usage: realpath [-LPemqsz] [--relative-base DIR] [-R DIR] FILE...\n\nDisplay the canonical absolute pathname\n\n-R Show ../path relative to DIR (--relative-to)\n-L Logical path (resolve .. before symlinks)\n-P Physical path (default)\n-e Canonical path to existing entry (fail if missing)\n-m Ignore missing entries, show where it would be\n-q Quiet (no error messages)\n-s Don't expand symlinks\n-z NUL instead of newline\n--relative-base  If path under DIR trim off prefix"
 
-#define HELP_readlink "usage: readlink FILE...\n\nWith no options, show what symlink points to, return error if not symlink.\n\nOptions for producing canonical paths (all symlinks/./.. resolved):\n\n-e	Canonical path to existing entry (fail if missing)\n-f	Full path (fail if directory missing)\n-m	Ignore missing entries, show where it would be\n-n	No trailing newline\n-q	Quiet (no output, just error code)"
+#define HELP_readlink "usage: readlink FILE...\n\nWith no options, show what symlink points to, return error if not symlink.\n\nOptions for producing canonical paths (all symlinks/./.. resolved):\n\n-e	Canonical path to existing entry (fail if missing)\n-f	Full path (fail if directory missing)\n-m	Ignore missing entries, show where it would be\n-n	No trailing newline\n-q	Quiet (no error messages)\n-z	NUL instead of newline"
 
 #define HELP_readelf "usage: readelf [-adehlnSs] [-p SECTION] [-x SECTION] [file...]\n\nDisplays information about ELF files.\n\n-a	Equivalent to -dhlnSs\n-d	Show dynamic section\n-e	Headers (equivalent to -hlS)\n-h	Show ELF header\n-l	Show program headers\n-n	Show notes\n-p S	Dump strings found in named/numbered section\n-S	Show section headers\n-s	Show symbol tables (.dynsym and .symtab)\n-x S	Hex dump of named/numbered section\n\n--dyn-syms	Show just .dynsym symbol table"
 
@@ -210,7 +216,7 @@
 
 #define HELP_printenv "usage: printenv [-0] [env_var...]\n\nPrint environment variables.\n\n-0	Use \\0 as delimiter instead of \\n"
 
-#define HELP_pmap "usage: pmap [-pqx] PID...\n\nReport the memory map of a process or processes.\n\n-q	Show full paths\n-q	Do not show header or footer\n-x	Show the extended format"
+#define HELP_pmap "usage: pmap [-pqx] PID...\n\nReport the memory map of a process or processes.\n\n-p	Show full paths\n-q	Do not show header or footer\n-x	Show the extended format"
 
 #define HELP_pivot_root "usage: pivot_root OLD NEW\n\nSwap OLD and NEW filesystems (as if by simultaneous mount --move), and\nmove all processes with chdir or chroot under OLD into NEW (including\nkernel threads) so OLD may be unmounted.\n\nThe directory NEW must exist under OLD. This doesn't work on initramfs,\nwhich can't be moved (about the same way PID 1 can't be killed; see\nswitch_root instead)."
 
@@ -224,11 +230,13 @@
 
 #define HELP_oneit "usage: oneit [-prn3] [-c CONSOLE] [COMMAND...]\n\nSimple init program that runs a single supplied command line with a\ncontrolling tty (so CTRL-C can kill it).\n\n-c	Which console device to use (/dev/console doesn't do CTRL-C, etc)\n-p	Power off instead of rebooting when command exits\n-r	Restart child when it exits\n-n	No reboot, just relaunch command line\n-3	Write 32 bit PID of each exiting reparented process to fd 3 of child\n	(Blocking writes, child must read to avoid eventual deadlock.)\n\nSpawns a single child process (because PID 1 has signals blocked)\nin its own session, reaps zombies until the child exits, then\nreboots the system (or powers off with -p, or restarts the child with -r).\n\nResponds to SIGUSR1 by halting the system, SIGUSR2 by powering off,\nand SIGTERM or SIGINT reboot."
 
-#define HELP_nsenter "usage: nsenter [-t pid] [-F] [-i] [-m] [-n] [-p] [-u] [-U] COMMAND...\n\nRun COMMAND in an existing (set of) namespace(s).\n\n-t	PID to take namespaces from    (--target)\n-F	don't fork, even if -p is used (--no-fork)\n\nThe namespaces to switch are:\n\n-i	SysV IPC: message queues, semaphores, shared memory (--ipc)\n-m	Mount/unmount tree (--mount)\n-n	Network address, sockets, routing, iptables (--net)\n-p	Process IDs and init, will fork unless -F is used (--pid)\n-u	Host and domain names (--uts)\n-U	UIDs, GIDs, capabilities (--user)\n\nIf -t isn't specified, each namespace argument must provide a path\nto a namespace file, ala \"-i=/proc/$PID/ns/ipc\""
+#define HELP_nsenter "usage: nsenter [-t pid] [-F] [-i] [-m] [-n] [-p] [-u] [-U] COMMAND...\n\nRun COMMAND in an existing (set of) namespace(s).\n\n-a	Enter all supported namespaces (--all)\n-F	don't fork, even if -p is used (--no-fork)\n-t	PID to take namespaces from    (--target)\n\nThe namespaces to switch are:\n\n-C	Control groups (--cgroup)\n-i	SysV IPC: message queues, semaphores, shared memory (--ipc)\n-m	Mount/unmount tree (--mount)\n-n	Network address, sockets, routing, iptables (--net)\n-p	Process IDs and init, will fork unless -F is used (--pid)\n-u	Host and domain names (--uts)\n-U	UIDs, GIDs, capabilities (--user)\n\nIf -t isn't specified, each namespace argument must provide a path\nto a namespace file, ala \"-i=/proc/$PID/ns/ipc\""
 
-#define HELP_unshare "usage: unshare [-imnpuUr] COMMAND...\n\nCreate new container namespace(s) for this process and its children, so\nsome attribute is not shared with the parent process.\n\n-f	Fork command in the background (--fork)\n-i	SysV IPC (message queues, semaphores, shared memory) (--ipc)\n-m	Mount/unmount tree (--mount)\n-n	Network address, sockets, routing, iptables (--net)\n-p	Process IDs and init (--pid)\n-r	Become root (map current euid/egid to 0/0, implies -U) (--map-root-user)\n-u	Host and domain names (--uts)\n-U	UIDs, GIDs, capabilities (--user)\n\nA namespace allows a set of processes to have a different view of the\nsystem than other sets of processes."
+#define HELP_unshare "usage: unshare [-imnpuUr] COMMAND...\n\nCreate new container namespace(s) for this process and its children, allowing\nthe new set of processes to have a different view of the system than the\nparent process.\n\n-a	Unshare all supported namespaces\n-f	Fork command in the background (--fork)\n-r	Become root (map current euid/egid to 0/0, implies -U) (--map-root-user)\n\nAvailable namespaces:\n-C	Control groups (--cgroup)\n-i	SysV IPC (message queues, semaphores, shared memory) (--ipc)\n-m	Mount/unmount tree (--mount)\n-n	Network address, sockets, routing, iptables (--net)\n-p	Process IDs and init (--pid)\n-u	Host and domain names (--uts)\n-U	UIDs, GIDs, capabilities (--user)\n\nEach namespace can take an optional argument, a persistent mountpoint usable\nby the nsenter command to add new processes to that the namespace. (Specify\nmultiple namespaces to unshare separately, ala -c -i -m because -cim is -c\nwith persistent mount \"im\".)"
 
-#define HELP_nbd_client "usage: nbd-client [-ns] HOST PORT DEVICE\n\n-n	Do not fork into background\n-s	nbd swap support (lock server into memory)"
+#define HELP_nbd_server "usage: nbd-server [-r] FILE\n\nServe a Network Block Device from FILE on stdin/out (ala inetd).\n\n-r	Read only export"
+
+#define HELP_nbd_client "usage: nbd-client [-ns] [-b BLKSZ] HOST PORT DEVICE\n\n-b	Block size (default 4096)\n-n	Do not daemonize\n-s	nbd swap support (lock server into memory)"
 
 #define HELP_mountpoint "usage: mountpoint [-qd] DIR\n       mountpoint [-qx] DEVICE\n\nCheck whether the directory or device is a mountpoint.\n\n-q	Be quiet, return zero if directory is a mountpoint\n-d	Print major/minor device number of the directory\n-x	Print major/minor device number of the block device"
 
@@ -246,7 +254,7 @@
 
 #define HELP_lsusb "usage: lsusb [-i]\n\nList USB hosts/devices.\n\n-i	ID database (default /etc/usb.ids[.gz])"
 
-#define HELP_lspci "usage: lspci [-ekmn] [-i FILE]\n\nList PCI devices.\n\n-e  Extended (6 digit) class\n-i  ID database (default /etc/pci.ids[.gz])\n-k  Show kernel driver\n-m  Machine readable\n-n  Numeric output (-nn for both)"
+#define HELP_lspci "usage: lspci [-ekmn] [-i FILE]\n\nList PCI devices.\n\n-e	Extended (6 digit) class\n-i	ID database (default /etc/pci.ids[.gz])\n-k	Show kernel driver\n-m	Machine readable\n-n	Numeric output (-nn for both)\n-x	Hex dump of config space (64 bytes; -xxx for 256, -xxxx for 4096)"
 
 #define HELP_lsmod "usage: lsmod\n\nDisplay the currently loaded modules, their sizes and their dependencies."
 
@@ -266,13 +274,13 @@
 
 #define HELP_inotifyd "usage: inotifyd PROG FILE[:MASK] ...\n\nWhen a filesystem event matching MASK occurs to a FILE, run PROG as:\n\n  PROG EVENTS FILE [DIRFILE]\n\nIf PROG is \"-\" events are sent to stdout.\n\nThis file is:\n  a  accessed    c  modified    e  metadata change  w  closed (writable)\n  r  opened      D  deleted     M  moved            0  closed (unwritable)\n  u  unmounted   o  overflow    x  unwatchable\n\nA file in this directory is:\n  m  moved in    y  moved out   n  created          d  deleted\n\nWhen x event happens for all FILEs, inotifyd exits (after waiting for PROG)."
 
-#define HELP_i2cset "usage: i2cset [-fy] BUS CHIP ADDR VALUE... MODE\n\nWrite an i2c register. MODE is b for byte, w for 16-bit word, i for I2C block.\n\n-f	Force access to busy devices\n-y	Answer \"yes\" to confirmation prompts (for script use)"
+#define HELP_i2cset "usage: i2cset [-fy] BUS CHIP ADDR VALUE... MODE\n\nWrite an i2c register. MODE is b for byte, w for 16-bit word, i for I2C block.\n\n-f	Force access to busy devices\n-y	Skip confirmation prompts (yes to all)"
 
-#define HELP_i2cget "usage: i2cget [-fy] BUS CHIP ADDR\n\nRead an i2c register.\n\n-f	Force access to busy devices\n-y	Answer \"yes\" to confirmation prompts (for script use)"
+#define HELP_i2cget "usage: i2cget [-fy] BUS CHIP [ADDR]\n\nRead an i2c register.\n\n-f	Force access to busy devices\n-y	Skip confirmation prompts (yes to all)"
 
-#define HELP_i2cdump "usage: i2cdump [-fy] BUS CHIP\n\nDump i2c registers.\n\n-f	Force access to busy devices\n-y	Answer \"yes\" to confirmation prompts (for script use)"
+#define HELP_i2cdump "usage: i2cdump [-fy] BUS CHIP\n\nDump i2c registers.\n\n-f	Force access to busy devices\n-y	Skip confirmation prompts (yes to all)"
 
-#define HELP_i2cdetect "usage: i2cdetect [-aqry] BUS [FIRST LAST]\nusage: i2cdetect -F BUS\nusage: i2cdetect -l\n\nDetect i2c devices.\n\n-a	All addresses (0x00-0x7f rather than 0x03-0x77 or FIRST-LAST)\n-F	Show functionality\n-l	List available buses\n-q	Probe with SMBus Quick Write (default)\n-r	Probe with SMBus Read Byte\n-y	Answer \"yes\" to confirmation prompts (for script use)"
+#define HELP_i2cdetect "usage: i2cdetect [-aqry] BUS [FIRST LAST]\nusage: i2cdetect -F BUS\nusage: i2cdetect -l\n\nDetect i2c devices.\n\n-a	All addresses (0x00-0x7f rather than 0x03-0x77 or FIRST-LAST)\n-F	Show functionality\n-l	List available buses\n-q	Probe with SMBus Quick Write (default)\n-r	Probe with SMBus Read Byte\n-y	Skip confirmation prompts (yes to all)"
 
 #define HELP_hwclock "usage: hwclock [-rswtluf]\n\nGet/set the hardware clock.\n\n-f FILE	Use specified device file instead of /dev/rtc0 (--rtc)\n-l	Hardware clock uses localtime (--localtime)\n-r	Show hardware clock time (--show)\n-s	Set system time from hardware clock (--hctosys)\n-t	Set the system time based on the current timezone (--systz)\n-u	Hardware clock uses UTC (--utc)\n-w	Set hardware clock from system time (--systohc)"
 
@@ -304,7 +312,7 @@
 
 #define HELP_fallocate "usage: fallocate [-l size] [-o offset] file\n\nTell the filesystem to allocate space for a file."
 
-#define HELP_factor "usage: factor NUMBER...\n\nFactor integers."
+#define HELP_factor "usage: factor NUMBER...\n\nFactor integers.\n\n-h	Human readable: show repeated factors as x^n\n-x	Hexadecimal output"
 
 #define HELP_eject "usage: eject [-stT] [DEVICE]\n\nEject DEVICE or default /dev/cdrom\n\n-s	SCSI device\n-t	Close tray\n-T	Open/close tray (toggle)"
 
@@ -332,7 +340,7 @@
 
 #define HELP_fstype "usage: fstype DEV...\n\nPrint type of filesystem on a block device or image."
 
-#define HELP_blkid "usage: blkid [-s TAG] [-UL] DEV...\n\nPrint type, label and UUID of filesystem on a block device or image.\n\n-U	Show UUID only (or device with that UUID)\n-L	Show LABEL only (or device with that LABEL)\n-s TAG	Only show matching tags (default all)"
+#define HELP_blkid "usage: blkid [-o TYPE] [-s TAG] [-UL] DEV...\n\nPrint type, label and UUID of filesystem on a block device or image.\n\n-U	Show UUID only (or device with that UUID)\n-L	Show LABEL only (or device with that LABEL)\n-o TYPE	Output format (full, value, export)\n-s TAG	Only show matching tags (default all)"
 
 #define HELP_blkdiscard "usage: blkdiscard [-olszf] DEVICE\n\nDiscard device sectors.\n\n-o, --offset OFF	Byte offset to start discarding at (default 0)\n-l, --length LEN	Bytes to discard (default all)\n-s, --secure		Perform secure discard\n-z, --zeroout		Zero-fill rather than discard\n-f, --force		Disable check for mounted filesystem\n\nOFF and LEN must be aligned to the device sector size.\nBy default entire device is discarded.\nWARNING: All discarded data is permanently lost!"
 
@@ -348,13 +356,7 @@
 
 #define HELP_xzcat "usage: xzcat [filename...]\n\nDecompress listed files to stdout. Use stdin if no files listed."
 
-#define HELP_wget_openssl "Enable HTTPS support for wget by linking to OpenSSL."
-
-#define HELP_wget_libtls "Enable HTTPS support for wget by linking to LibTLS.\nSupports using libtls, libretls or libtls-bearssl."
-
-#define HELP_wget "usage: wget [OPTIONS]... [URL]\n    --max-redirect          maximum redirections allowed\n-d, --debug                 print lots of debugging information\n-O, --output-document=FILE  specify output filename\n-p, --post-data=DATA        send data in body of POST request\n\nexamples:\n  wget http://www.example.com"
-
-#define HELP_vi "usage: vi [-s script] FILE\n-s script: run script file\nVisual text editor. Predates the existence of standardized cursor keys,\nso the controls are weird and historical."
+#define HELP_vi "usage: vi [-s script] FILE\n\nVisual text editor. Predates the existence of standardized cursor keys,\nso the controls are weird and historical.\n\n-s script: run script file"
 
 #define HELP_userdel "usage: userdel [-r] USER\nusage: deluser [-r] USER\n\nDelete USER from the SYSTEM\n\n-r	remove home directory"
 
@@ -408,7 +410,7 @@
 
 #define HELP_cd "usage: cd [-PL] [-] [path]\n\nChange current directory. With no arguments, go $HOME. Sets $OLDPWD to\nprevious directory: cd - to return to $OLDPWD.\n\n-P	Physical path: resolve symlinks in path\n-L	Local path: .. trims directories off $PWD (default)"
 
-#define HELP_sh "usage: sh [-c command] [script]\n\nCommand shell.  Runs a shell script, or reads input interactively\nand responds to it.\n\n-c	command line to execute\n-i	interactive mode (default when STDIN is a tty)"
+#define HELP_sh "usage: sh [-c command] [script]\n\nCommand shell.  Runs a shell script, or reads input interactively\nand responds to it. Roughly compatible with \"bash\". Run \"help\" for\nlist of built-in commands.\n\n-c	command line to execute\n-i	interactive mode (default when STDIN is a tty)\n-s	don't run script (args set $* parameters but read commands from stdin)\n\nCommand shells parse each line of input (prompting when interactive), perform\nvariable expansion and redirection, execute commands (spawning child processes\nand background jobs), and perform flow control based on the return code.\n\nParsing:\n  syntax errors\n\nInteractive prompts:\n  line continuation\n\nVariable expansion:\n  Note: can cause syntax errors at runtime\n\nRedirection:\n  HERE documents (parsing)\n  Pipelines (flow control and job control)\n\nRunning commands:\n  process state\n  builtins\n    cd [[ ]] (( ))\n    ! : [ # TODO: help for these?\n    true false help echo kill printf pwd test\n  child processes\n\nJob control:\n  &    Background process\n  Ctrl-C kill process\n  Ctrl-Z suspend process\n  bg fg jobs kill\n\nFlow control:\n;    End statement (same as newline)\n&    Background process (returns true unless syntax error)\n&&   If this fails, next command fails without running\n||   If this succeeds, next command succeeds without running\n|    Pipelines! (Can of worms...)\nfor {name [in...]}|((;;)) do; BODY; done\nif TEST; then BODY; fi\nwhile TEST; do BODY; done\ncase a in X);; esac\n[[ TEST ]]\n((MATH))\n\nJob control:\n&    Background process\nCtrl-C kill process\nCtrl-Z suspend process\nbg fg jobs kill"
 
 #define HELP_route "usage: route [-ne] [-A [inet|inet6]] [add|del TARGET [OPTIONS]]\n\nDisplay, add or delete network routes in the \"Forwarding Information Base\",\nwhich send packets out a network interface to an address.\n\n-n	Show numerical addresses (no DNS lookups)\n-e	display netstat fields\n\nAssigning an address to an interface automatically creates an appropriate\nnetwork route (\"ifconfig eth0 10.0.2.15/8\" does \"route add 10.0.0.0/8 eth0\"\nfor you), although some devices (such as loopback) won't show it in the\ntable. For machines more than one hop away, you need to specify a gateway\n(ala \"route add default gw 10.0.2.2\").\n\nThe address \"default\" is a wildcard address (0.0.0.0/0) matching all\npackets without a more specific route.\n\nAvailable OPTIONS include:\nreject   - blocking route (force match failure)\ndev NAME - force matching packets out this interface (ala \"eth0\")\nnetmask  - old way of saying things like ADDR/24\ngw ADDR  - forward packets to gateway ADDR"
 
@@ -454,6 +456,18 @@
 
 #define HELP_groupadd "usage: groupadd [-S] [-g GID] [USER] GROUP\n\nAdd a group or add a user to a group\n\n  -g GID Group id\n  -S     Create a system group"
 
+#define HELP_gitcheckout "usage: gitcheckout <branch>\nA minimal git checkout."
+
+#define HELP_gitfetch "usage: gitfetch\nA minimal git fetch."
+
+#define HELP_gitremote "usage: gitremote URL\nA minimal git remote add origin."
+
+#define HELP_gitinit "usage: gitinit NAME\nA minimal git init."
+
+#define HELP_gitclone "usage: gitclone URL\nA minimal git clone."
+
+#define HELP_gitcompat "Enable git compatible repos instead of minimal clone downloader."
+
 #define HELP_getty "usage: getty [OPTIONS] BAUD_RATE[,BAUD_RATE]... TTY [TERMTYPE]\n\nWait for a modem to dial into serial port, adjust baud rate, call login.\n\n-h    Enable hardware RTS/CTS flow control\n-L    Set CLOCAL (ignore Carrier Detect state)\n-m    Get baud rate from modem's CONNECT status message\n-n    Don't prompt for login name\n-w    Wait for CR or LF before sending /etc/issue\n-i    Don't display /etc/issue\n-f ISSUE_FILE  Display ISSUE_FILE instead of /etc/issue\n-l LOGIN  Invoke LOGIN instead of /bin/login\n-t SEC    Terminate after SEC if no login name is read\n-I INITSTR  Send INITSTR before anything else\n-H HOST    Log HOST into the utmp file as the hostname"
 
 #define HELP_getopt "usage: getopt [OPTIONS] [--] ARG...\n\nParse command-line options for use in shell scripts.\n\n-a	Allow long options starting with a single -.\n-l OPTS	Specify long options.\n-n NAME	Command name for error messages.\n-o OPTS	Specify short options.\n-T	Test whether this is a modern getopt.\n-u	Output options unquoted."
@@ -470,7 +484,7 @@
 
 #define HELP_dumpleases "usage: dumpleases [-r|-a] [-f LEASEFILE]\n\nDisplay DHCP leases granted by udhcpd\n-f FILE,  Lease file\n-r        Show remaining time\n-a        Show expiration time"
 
-#define HELP_diff "usage: diff [-abBdiNqrTstw] [-L LABEL] [-S FILE] [-U LINES] FILE1 FILE2\n\n-a	Treat all files as text\n-b	Ignore changes in the amount of whitespace\n-B	Ignore changes whose lines are all blank\n-d	Try hard to find a smaller set of changes\n-i	Ignore case differences\n-L	Use LABEL instead of the filename in the unified header\n-N	Treat absent files as empty\n-q	Output only whether files differ\n-r	Recurse\n-S	Start with FILE when comparing directories\n-T	Make tabs line up by prefixing a tab when necessary\n-s	Report when two files are the same\n-t	Expand tabs to spaces in output\n-u	Unified diff\n-U	Output LINES lines of context\n-w	Ignore all whitespace\n\n--color              Colored output\n--strip-trailing-cr  Strip trailing '\\r's from input lines"
+#define HELP_diff "usage: diff [-abBdiNqrTstw] [-L LABEL] [-S FILE] [-U LINES] [-F REGEX ] FILE1 FILE2\n\n-a	Treat all files as text\n-b	Ignore changes in the amount of whitespace\n-B	Ignore changes whose lines are all blank\n-d	Try hard to find a smaller set of changes\n-F 	Show the most recent line matching the regex\n-i	Ignore case differences\n-L	Use LABEL instead of the filename in the unified header\n-N	Treat absent files as empty\n-q	Output only whether files differ\n-r	Recurse\n-S	Start with FILE when comparing directories\n-s	Report when two files are the same\n-T	Make tabs line up by prefixing a tab when necessary\n-t	Expand tabs to spaces in output\n-u	Unified diff\n-U	Output LINES lines of context\n-w	Ignore all whitespace\n\n--color     Color output   --strip-trailing-cr   Strip '\\r' from input lines\n--TYPE-line-format=FORMAT  Display TYPE (unchanged/old/new) lines using FORMAT\n  FORMAT uses printf integer escapes (ala %-2.4x) followed by LETTER: FELMNn\nSupported format specifiers are:\n* %l, the contents of the line, without the trailing newline\n* %L, the contents of the line, including the trailing newline\n* %%, the character '%'"
 
 #define HELP_dhcpd "usage: dhcpd [-46fS] [-i IFACE] [-P N] [CONFFILE]\n\n -f    Run in foreground\n -i Interface to use\n -S    Log to syslog too\n -P N  Use port N (default ipv4 67, ipv6 547)\n -4, -6    Run as a DHCPv4 or DHCPv6 server"
 
@@ -478,7 +492,7 @@
 
 #define HELP_dhcp "usage: dhcp [-fbnqvoCRB] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n            [-H HOSTNAME] [-V VENDOR] [-x OPT:VAL] [-O OPT]\n\n     Configure network dynamically using DHCP.\n\n   -i Interface to use (default eth0)\n   -p Create pidfile\n   -s Run PROG at DHCP events (default /usr/share/dhcp/default.script)\n   -B Request broadcast replies\n   -t Send up to N discover packets\n   -T Pause between packets (default 3 seconds)\n   -A Wait N seconds after failure (default 20)\n   -f Run in foreground\n   -b Background if lease is not obtained\n   -n Exit if lease is not obtained\n   -q Exit after obtaining lease\n   -R Release IP on exit\n   -S Log to syslog too\n   -a Use arping to validate offered address\n   -O Request option OPT from server (cumulative)\n   -o Don't request any options (unless -O is given)\n   -r Request this IP address\n   -x OPT:VAL  Include option OPT in sent packets (cumulative)\n   -F Ask server to update DNS mapping for NAME\n   -H Send NAME as client hostname (default none)\n   -V VENDOR Vendor identifier (default 'toybox VERSION')\n   -C Don't send MAC as client identifier\n   -v Verbose\n\n   Signals:\n   USR1  Renew current lease\n   USR2  Release current lease"
 
-#define HELP_dd "usage: dd [if=FILE] [of=FILE] [ibs=N] [obs=N] [iflag=FLAGS] [oflag=FLAGS]\n        [bs=N] [count=N] [seek=N] [skip=N]\n        [conv=notrunc|noerror|sync|fsync] [status=noxfer|none]\n\nCopy/convert files.\n\nif=FILE		Read from FILE instead of stdin\nof=FILE		Write to FILE instead of stdout\nbs=N		Read and write N bytes at a time\nibs=N		Input block size\nobs=N		Output block size\ncount=N		Copy only N input blocks\nskip=N		Skip N input blocks\nseek=N		Skip N output blocks\niflag=FLAGS	Set input flags\noflag=FLAGS	Set output flags\nconv=notrunc	Don't truncate output file\nconv=noerror	Continue after read errors\nconv=sync	Pad blocks with zeros\nconv=fsync	Physically write data out before finishing\nstatus=noxfer	Don't show transfer rate\nstatus=none	Don't show transfer rate or records in/out\n\nFLAGS is a comma-separated list of:\n\ncount_bytes	(iflag) interpret count=N in bytes, not blocks\nseek_bytes	(oflag) interpret seek=N in bytes, not blocks\nskip_bytes	(iflag) interpret skip=N in bytes, not blocks\n\nNumbers may be suffixed by c (*1), w (*2), b (*512), kD (*1000), k (*1024),\nMD (*1000*1000), M (*1024*1024), GD (*1000*1000*1000) or G (*1024*1024*1024)."
+#define HELP_dd "usage: dd [if|of=FILE] [ibs|obs|bs|count|seek|skip=N] [conv|status|iflag|oflag=FLAG[,FLAG...]]\n\nCopy/convert blocks of data from input to output, with the following\nkeyword=value modifiers (and their default values):\n\nif=FILE  Read FILE (stdin)          of=FILE  Write to FILE (stdout)\n   bs=N  Block size in bytes (512)  count=N  Stop after copying N blocks\n  ibs=N  Input block size (bs=)       obs=N  Output block size (bs=)\n skip=N  Skip N input blocks (0)     seek=N  Skip N output blocks (0)\n\nEach =N value accepts the normal unit suffixes (see toybox --help).\n\nThese modifiers take a comma separated list of potential options:\n\niflag=count_bytes,skip_bytes   count=N or skip=N is in bytes not blocks\noflag=seek_bytes,append        seek=N is in bytes, append output to file\nstatus=noxfer,none             don't show transfer rate, no summary info\nconv=\n  notrunc  Don't truncate output    noerror  Continue after read errors\n  sync     Zero pad short reads     fsync    Flush output to disk at end\n  sparse   Seek past zeroed output  excl     Fail if output file exists\n  nocreat  Fail if of=FILE missing"
 
 #define HELP_crontab "usage: crontab [-u user] FILE\n               [-u user] [-e | -l | -r]\n               [-c dir]\n\nFiles used to schedule the execution of programs.\n\n-c crontab dir\n-e edit user's crontab\n-l list user's crontab\n-r delete user's crontab\n-u user\nFILE Replace crontab by FILE ('-': stdin)"
 
@@ -488,7 +502,7 @@
 
 #define HELP_brctl "usage: brctl COMMAND [BRIDGE [INTERFACE]]\n\nManage ethernet bridges\n\nCommands:\nshow                  Show a list of bridges\naddbr BRIDGE          Create BRIDGE\ndelbr BRIDGE          Delete BRIDGE\naddif BRIDGE IFACE    Add IFACE to BRIDGE\ndelif BRIDGE IFACE    Delete IFACE from BRIDGE\nsetageing BRIDGE TIME Set ageing time\nsetfd BRIDGE TIME     Set bridge forward delay\nsethello BRIDGE TIME  Set hello time\nsetmaxage BRIDGE TIME Set max message age\nsetpathcost BRIDGE PORT COST   Set path cost\nsetportprio BRIDGE PORT PRIO   Set port priority\nsetbridgeprio BRIDGE PRIO      Set bridge priority\nstp BRIDGE [1/yes/on|0/no/off] STP on/off"
 
-#define HELP_bootchartd "usage: bootchartd {start [PROG ARGS]}|stop|init\n\nCreate /var/log/bootlog.tgz with boot chart data\n\nstart: start background logging; with PROG, run PROG,\n       then kill logging with USR1\nstop:  send USR1 to all bootchartd processes\ninit:  start background logging; stop when getty/xdm is seen\n      (for init scripts)\n\nUnder PID 1: as init, then exec $bootchart_init, /init, /sbin/init"
+#define HELP_bootchartd "usage: bootchartd {start [PROG ARGS]}|stop|init\n\nRecord boot chart data into /var/log/bootlog.tgz\n\nstart: start background logging; with PROG, run PROG,\n       then kill logging with SIGUSR1\nstop:  send SIGUSR1 to all bootchartd processes\ninit:  start background logging; stop when getty/xdm is seen\n      (for init scripts)\n\nUnder PID 1: as init, then exec $bootchart_init, /init, /sbin/init"
 
 #define HELP_bc "usage: bc [-ilqsw] [file ...]\n\nbc is a command-line calculator with a Turing-complete language.\n\noptions:\n\n  -i  --interactive  force interactive mode\n  -l  --mathlib      use predefined math routines:\n\n                     s(expr)  =  sine of expr in radians\n                     c(expr)  =  cosine of expr in radians\n                     a(expr)  =  arctangent of expr, returning radians\n                     l(expr)  =  natural log of expr\n                     e(expr)  =  raises e to the power of expr\n                     j(n, x)  =  Bessel function of integer order n of x\n\n  -q  --quiet        don't print version and copyright\n  -s  --standard     error if any non-POSIX extensions are used\n  -w  --warn         warn if any non-POSIX extensions are used"
 
@@ -526,11 +540,11 @@
 
 #define HELP_time "usage: time [-pv] COMMAND...\n\nRun command line and report real, user, and system time elapsed in seconds.\n(real = clock on the wall, user = cpu used by command's code,\nsystem = cpu used by OS on behalf of command.)\n\n-p	POSIX format output\n-v	Verbose"
 
-#define HELP_test "usage: test [-bcdefghLPrSsuwx PATH] [-nz STRING] [-t FD] [X ?? Y]\n\nReturn true or false by performing tests. (With no arguments return false.)\n\n--- Tests with a single argument (after the option):\nPATH is/has:\n  -b  block device   -f  regular file   -p  fifo           -u  setuid bit\n  -c  char device    -g  setgid         -r  read bit       -w  write bit\n  -d  directory      -h  symlink        -S  socket         -x  execute bit\n  -e  exists         -L  symlink        -s  nonzero size   -k  sticky bit\nSTRING is:\n  -n  nonzero size   -z  zero size      (STRING by itself implies -n)\nFD (integer file descriptor) is:\n  -t  a TTY\n\n--- Tests with one argument on each side of an operator:\nTwo strings:\n  =  are identical   !=  differ\n\nTwo integers:\n  -eq  equal         -gt  first > second    -lt  first < second\n  -ne  not equal     -ge  first >= second   -le  first <= second\n\n--- Modify or combine tests:\n  ! EXPR     not (swap true/false)   EXPR -a EXPR    and (are both true)\n  ( EXPR )   evaluate this first     EXPR -o EXPR    or (is either true)"
+#define HELP_test "usage: test [-bcdefghLPrSsuwx PATH] [-nz STRING] [-t FD] [X ?? Y]\n\nReturn true or false by performing tests. No arguments is false, one argument\nis true if not empty string.\n\n--- Tests with a single argument (after the option):\nPATH is/has:\n  -b  block device   -f  regular file   -p  fifo           -u  setuid bit\n  -c  char device    -g  setgid         -r  readable       -w  writable\n  -d  directory      -h  symlink        -S  socket         -x  executable\n  -e  exists         -L  symlink        -s  nonzero size   -k  sticky bit\nSTRING is:\n  -n  nonzero size   -z  zero size\nFD (integer file descriptor) is:\n  -t  a TTY          -T  open\n\n--- Tests with one argument on each side of an operator:\nTwo strings:\n  =  are identical   !=  differ         =~  string matches regex\nAlphabetical sort:\n  <  first is lower  >   first higher\nTwo integers:\n  -eq  equal         -gt  first > second    -lt  first < second\n  -ne  not equal     -ge  first >= second   -le  first <= second\n\n--- Modify or combine tests:\n  ! EXPR     not (swap true/false)   EXPR -a EXPR    and (are both true)\n  ( EXPR )   evaluate this first     EXPR -o EXPR    or (is either true)"
 
 #define HELP_tee "usage: tee [-ai] [FILE...]\n\nCopy stdin to each listed file, and also to stdout.\nFilename \"-\" is a synonym for stdout.\n\n-a	Append to files\n-i	Ignore SIGINT"
 
-#define HELP_tar "usage: tar [-cxt] [-fvohmjkOS] [-XTCf NAME] [--selinux] [FILE...]\n\nCreate, extract, or list files in a .tar (or compressed t?z) file.\n\nOptions:\nc  Create                x  Extract               t  Test (list)\nf  tar FILE (default -)  C  Change to DIR first   v  Verbose display\no  Ignore owner          h  Follow symlinks       m  Ignore mtime\nJ  xz compression        j  bzip2 compression     z  gzip compression\nO  Extract to stdout     X  exclude names in FILE T  include names in FILE\n\n--exclude        FILENAME to exclude  --full-time         Show seconds with -tv\n--mode MODE      Adjust permissions   --owner NAME[:UID]  Set file ownership\n--mtime TIME     Override timestamps  --group NAME[:GID]  Set file group\n--sparse         Record sparse files  --selinux           Save/restore labels\n--restrict       All under one dir    --no-recursion      Skip dir contents\n--numeric-owner  Use numeric uid/gid, not user/group names\n--strip-components NUM  Ignore first NUM directory components when extracting\n-I PROG          Filter through PROG to compress or PROG -d to decompress"
+#define HELP_tar "usage: tar [-cxt] [-fvohmjkOS] [-XTCf NAME] [--selinux] [FILE...]\n\nCreate, extract, or list files in a .tar (or compressed t?z) file.\n\nOptions:\nc  Create                x  Extract               t  Test (list)\nf  tar FILE (default -)  C  Change to DIR first   v  Verbose display\nJ  xz compression        j  bzip2 compression     z  gzip compression\no  Ignore owner          h  Follow symlinks       m  Ignore mtime\nO  Extract to stdout     X  exclude names in FILE T  include names in FILE\ns  Sort dirs (--sort)\n\n--exclude        FILENAME to exclude  --full-time         Show seconds with -tv\n--mode MODE      Adjust permissions   --owner NAME[:UID]  Set file ownership\n--mtime TIME     Override timestamps  --group NAME[:GID]  Set file group\n--sparse         Record sparse files  --selinux           Save/restore labels\n--restrict       All under one dir    --no-recursion      Skip dir contents\n--numeric-owner  Use numeric uid/gid, not user/group names\n--null           Filenames in -T FILE are null-separated, not newline\n--strip-components NUM  Ignore first NUM directory components when extracting\n--xform=SED      Modify filenames via SED expression (ala s/find/replace/g)\n-I PROG          Filter through PROG to compress or PROG -d to decompress\n\nFilename filter types. Create command line args aren't filtered, extract\ndefaults to --anchored, --exclude defaults to --wildcards-match-slash,\nuse no- prefix to disable:\n\n--anchored  Match name not path       --ignore-case       Case insensitive\n--wildcards Expand *?[] like shell    --wildcards-match-slash"
 
 #define HELP_tail "usage: tail [-n|c NUMBER] [-f|F] [-s SECONDS] [FILE...]\n\nCopy last lines from files to stdout. If no files listed, copy from\nstdin. Filename \"-\" is a synonym for stdin.\n\n-n	Output the last NUMBER lines (default 10), +X counts from start\n-c	Output the last NUMBER bytes, +NUMBER counts from start\n-f	Follow FILE(s) by descriptor, waiting for more data to be appended\n-F	Follow FILE(s) by filename, waiting for more data, and retrying\n-s	Used with -F, sleep SECONDS between retries (default 1)"
 
@@ -538,11 +552,11 @@
 
 #define HELP_split "usage: split [-a SUFFIX_LEN] [-b BYTES] [-l LINES] [-n PARTS] [INPUT [OUTPUT]]\n\nCopy INPUT (or stdin) data to a series of OUTPUT (or \"x\") files with\nalphabetically increasing suffix (aa, ab, ac... az, ba, bb...).\n\n-a	Suffix length (default 2)\n-b	BYTES/file (10, 10k, 10m, 10g...)\n-l	LINES/file (default 1000)\n-n	PARTS many equal length files"
 
-#define HELP_sort "usage: sort [-Mbcdfginrsuz] [FILE...] [-k#[,#[x]] [-t X]] [-o FILE]\n\nSort all lines of text from input files (or stdin) to stdout.\n-M	Month sort (jan, feb, etc)\n-V	Version numbers (name-1.234-rc6.5b.tgz)\n-b	Ignore leading blanks (or trailing blanks in second part of key)\n-c	Check whether input is sorted\n-d	Dictionary order (use alphanumeric and whitespace chars only)\n-f	Force uppercase (case insensitive sort)\n-g	General numeric sort (double precision with nan and inf)\n-i	Ignore nonprinting characters\n-k	Sort by \"key\" (see below)\n-n	Numeric order (instead of alphabetical)\n-o	Output to FILE instead of stdout\n-r	Reverse\n-s	Skip fallback sort (only sort with keys)\n-t	Use a key separator other than whitespace\n-u	Unique lines only\n-x	Hexadecimal numerical sort\n-z	Zero (null) terminated lines\n\nSorting by key looks at a subset of the words on each line. -k2 uses the\nsecond word to the end of the line, -k2,2 looks at only the second word,\n-k2,4 looks from the start of the second to the end of the fourth word.\n-k2.4,5 starts from the fourth character of the second word, to the end\nof the fifth word. Specifying multiple keys uses the later keys as tie\nbreakers, in order. A type specifier appended to a sort key (such as -2,2n)\napplies only to sorting that key."
+#define HELP_sort "usage: sort [-Mbcdfginrsuz] [FILE...] [-k#[,#[x]] [-t X]] [-o FILE]\n\nSort all lines of text from input files (or stdin) to stdout.\n-C	Check whether input is sorted\n-M	Month sort (jan, feb, etc)\n-V	Version numbers (name-1.234-rc6.5b.tgz)\n-b	Ignore leading blanks (or trailing blanks in second part of key)\n-c	Warn if input is unsorted\n-d	Dictionary order (use alphanumeric and whitespace chars only)\n-f	Force uppercase (case insensitive sort)\n-g	General numeric sort (double precision with nan and inf)\n-i	Ignore nonprinting characters\n-k	Sort by \"key\" (see below)\n-n	Numeric order (instead of alphabetical)\n-o	Output to FILE instead of stdout\n-r	Reverse\n-s	Skip fallback sort (only sort with keys)\n-t	Use a key separator other than whitespace\n-u	Unique lines only\n-x	Hexadecimal numerical sort\n-z	Zero (null) terminated lines\n\nSorting by key looks at a subset of the words on each line. -k2 uses the\nsecond word to the end of the line, -k2,2 looks at only the second word,\n-k2,4 looks from the start of the second to the end of the fourth word.\n-k2.4,5 starts from the fourth character of the second word, to the end\nof the fifth word. Specifying multiple keys uses the later keys as tie\nbreakers, in order. A type specifier appended to a sort key (such as -2,2n)\napplies only to sorting that key."
 
-#define HELP_sleep "usage: sleep DURATION\n\nWait before exiting.\n\nDURATION can be a decimal fraction. An optional suffix can be \"m\"\n(minutes), \"h\" (hours), \"d\" (days), or \"s\" (seconds, the default)."
+#define HELP_sleep "usage: sleep DURATION...\n\nWait before exiting.\n\nDURATION can be a decimal fraction. An optional suffix can be \"m\"\n(minutes), \"h\" (hours), \"d\" (days), or \"s\" (seconds, the default)."
 
-#define HELP_sed "usage: sed [-inrszE] [-e SCRIPT]...|SCRIPT [-f SCRIPT_FILE]... [FILE...]\n\nStream editor. Apply editing SCRIPTs to lines of input.\n\n-e	Add SCRIPT to list\n-f	Add contents of SCRIPT_FILE to list\n-i	Edit each file in place (-iEXT keeps backup file with extension EXT)\n-n	No default output (use the p command to output matched lines)\n-r	Use extended regular expression syntax\n-E	POSIX alias for -r\n-s	Treat input files separately (implied by -i)\n-z	Use \\0 rather than \\n as input line separator\n\nA SCRIPT is one or more COMMANDs separated by newlines or semicolons.\nAll -e SCRIPTs are combined as if separated by newlines, followed by all -f\nSCRIPT_FILEs. If no -e or -f then first argument is the SCRIPT.\n\nCOMMANDs apply to every line unless prefixed with an ADDRESS of the form:\n\n  [ADDRESS[,ADDRESS]][!]COMMAND\n\nADDRESS is a line number (starting at 1), a /REGULAR EXPRESSION/, or $ for\nlast line (-s or -i makes it last line of each file). One address matches one\nline, ADDRESS,ADDRESS matches from first to second inclusive. Two regexes can\nmatch multiple ranges. ADDRESS,+N ends N lines later. ! inverts the match.\n\nREGULAR EXPRESSIONS start and end with the same character (anything but\nbackslash or newline). To use the delimiter in the regex escape it with a\nbackslash, and printf escapes (\\abcefnrtv and octal, hex, and unicode) work.\nAn empty regex repeats the previous one. ADDRESS regexes require any\nfirst delimiter except / to be \\escaped to distinguish it from COMMANDs.\n\nSed reads each line of input, processes it, and writes it out or discards it\nbefore reading the next. Sed can remember one additional line in a separate\nbuffer (the h, H, g, G, and x commands), and can read the next line of input\nearly (the n and N commands), but otherwise operates on individual lines.\n\nEach COMMAND starts with a single character. Commands with no arguments are:\n\n  !  Run this command when the ADDRESS _didn't_ match.\n  {  Start new command block, continuing until a corresponding \"}\".\n     Command blocks nest and can have ADDRESSes applying to the whole block.\n  }  End command block (this COMMAND cannot have an address)\n  d  Delete this line and move on to the next one\n     (ignores remaining COMMANDs)\n  D  Delete one line of input and restart command SCRIPT (same as \"d\"\n     unless you've glued lines together with \"N\" or similar)\n  g  Get remembered line (overwriting current line)\n  G  Get remembered line (appending to current line)\n  h  Remember this line (overwriting remembered line)\n  H  Remember this line (appending to remembered line, if any)\n  l  Print line escaping \\abfrtv (but not \\n), octal escape other nonprintng\n     chars, wrap lines to terminal width with \\, append $ to end of line.\n  n  Print default output and read next line over current line (quit at EOF)\n  N  Append \\n and next line of input to this line. Quit at EOF without\n     default output. Advances line counter for ADDRESS and \"=\".\n  p  Print this line\n  P  Print this line up to first newline (from \"N\")\n  q  Quit (print default output, no more commands processed or lines read)\n  x  Exchange this line with remembered line (overwrite in both directions)\n  =  Print the current line number (plus newline)\n  #  Comment, ignores rest of this line of SCRIPT (until newline)\n\nCommands that take an argument:\n\n  : LABEL    Target for jump commands\n  a TEXT     Append text to output before reading next line\n  b LABEL    Branch, jumps to :LABEL (with no LABEL to end of SCRIPT)\n  c TEXT     Delete matching ADDRESS range and output TEXT instead\n  i TEXT     Insert text (output immediately)\n  r FILE     Append contents of FILE to output before reading next line.\n  s/S/R/F    Search for regex S replace match with R using flags F. Delimiter\n             is anything but \\n or \\, escape with \\ to use in S or R. Printf\n             escapes work. Unescaped & in R becomes full matched text, \\1\n             through \\9 = parenthetical subexpression from S. \\ at end of\n             line appends next line of SCRIPT. The flags in F are:\n             [0-9]    A number N, substitute only Nth match\n             g        Global, substitute all matches\n             i/I      Ignore case when matching\n             p        Print resulting line when match found and replaced\n             w [file] Write (append) line to file when match replaced\n  t LABEL    Test, jump if s/// command matched this line since last test\n  T LABEL    Test false, jump to :LABEL only if no s/// found a match\n  w FILE     Write (append) line to file\n  y/old/new/ Change each character in 'old' to corresponding character\n             in 'new' (with standard backslash escapes, delimiter can be\n             any repeated character except \\ or \\n)\n\nThe TEXT arguments (to a c i) may end with an unescaped \"\\\" to append\nthe next line (leading whitespace is not skipped), and treat \";\" as a\nliteral character (use \"\\;\" instead)."
+#define HELP_sed "usage: sed [-inrszE] [-e SCRIPT]...|SCRIPT [-f SCRIPT_FILE]... [FILE...]\n\nStream editor. Apply editing SCRIPTs to lines of input.\n\n-e	Add SCRIPT to list\n-f	Add contents of SCRIPT_FILE to list\n-i	Edit each file in place (-iEXT keeps backup file with extension EXT)\n-n	No default output (use the p command to output matched lines)\n-r	Use extended regular expression syntax\n-E	POSIX alias for -r\n-s	Treat input files separately (implied by -i)\n-z	Use \\0 rather than \\n as input line separator\n\nA SCRIPT is one or more COMMANDs separated by newlines or semicolons.\nAll -e SCRIPTs are combined as if separated by newlines, followed by all -f\nSCRIPT_FILEs. If no -e or -f then first argument is the SCRIPT.\n\nCOMMANDs apply to every line unless prefixed with an ADDRESS of the form:\n\n  [ADDRESS[,ADDRESS]][!]COMMAND\n\nADDRESS is a line number (starting at 1), a /REGULAR EXPRESSION/, or $ for\nlast line (-s or -i makes it last line of each file). One address matches one\nline, ADDRESS,ADDRESS matches from first to second inclusive. Two regexes can\nmatch multiple ranges. ADDRESS,+N ends N lines later. ! inverts the match.\n\nREGULAR EXPRESSIONS start and end with the same character (anything but\nbackslash or newline). To use the delimiter in the regex escape it with a\nbackslash, and printf escapes (\\abcefnrtv and octal, hex, and unicode) work.\nAn empty regex repeats the previous one. ADDRESS regexes require any\nfirst delimiter except / to be \\escaped to distinguish it from COMMANDs.\n\nSed reads each line of input, processes it, and writes it out or discards it\nbefore reading the next. Sed can remember one additional line in a separate\nbuffer (the h, H, g, G, and x commands), and can read the next line of input\nearly (the n and N commands), but otherwise operates on individual lines.\n\nEach COMMAND starts with a single character. Commands with no arguments are:\n\n  !  Run this command when the ADDRESS _didn't_ match.\n  {  Start new command block, continuing until a corresponding \"}\".\n     Command blocks nest and can have ADDRESSes applying to the whole block.\n  }  End command block (this COMMAND cannot have an address)\n  d  Delete this line and move on to the next one\n     (ignores remaining COMMANDs)\n  D  Delete one line of input and restart command SCRIPT (same as \"d\"\n     unless you've glued lines together with \"N\" or similar)\n  g  Get remembered line (overwriting current line)\n  G  Get remembered line (appending to current line)\n  h  Remember this line (overwriting remembered line)\n  H  Remember this line (appending to remembered line, if any)\n  l  Print line escaping \\abfrtvn, octal escape other nonprintng chars,\n     wrap lines to terminal width with \\, append $ to end of line.\n  n  Print default output and read next line over current line (quit at EOF)\n  N  Append \\n and next line of input to this line. Quit at EOF without\n     default output. Advances line counter for ADDRESS and \"=\".\n  p  Print this line\n  P  Print this line up to first newline (from \"N\")\n  q  Quit (print default output, no more commands processed or lines read)\n  x  Exchange this line with remembered line (overwrite in both directions)\n  =  Print the current line number (plus newline)\n  #  Comment, ignores rest of this line of SCRIPT (until newline)\n\nCommands that take an argument:\n\n  : LABEL    Target for jump commands\n  a TEXT     Append text to output before reading next line\n  b LABEL    Branch, jumps to :LABEL (with no LABEL to end of SCRIPT)\n  c TEXT     Delete matching ADDRESS range and output TEXT instead\n  i TEXT     Insert text (output immediately)\n  r FILE     Append contents of FILE to output before reading next line.\n  s/S/R/F    Search for regex S replace match with R using flags F. Delimiter\n             is anything but \\n or \\, escape with \\ to use in S or R. Printf\n             escapes work. Unescaped & in R becomes full matched text, \\1\n             through \\9 = parenthetical subexpression from S. \\ at end of\n             line appends next line of SCRIPT. The flags in F are:\n             [0-9]    A number N, substitute only Nth match\n             g        Global, substitute all matches\n             i/I      Ignore case when matching\n             p        Print resulting line when match found and replaced\n             w [file] Write (append) line to file when match replaced\n  t LABEL    Test, jump if s/// command matched this line since last test\n  T LABEL    Test false, jump to :LABEL only if no s/// found a match\n  w FILE     Write (append) line to file\n  y/old/new/ Change each character in 'old' to corresponding character\n             in 'new' (with standard backslash escapes, delimiter can be\n             any repeated character except \\ or \\n)\n\nThe TEXT arguments (to a c i) may end with an unescaped \"\\\" to append\nthe next line (leading whitespace is not skipped), and treat \";\" as a\nliteral character (use \"\\;\" instead)."
 
 #define HELP_rmdir "usage: rmdir [-p] [DIR...]\n\nRemove one or more directories.\n\n-p	Remove path\n--ignore-fail-on-non-empty	Ignore failures caused by non-empty directories"
 
@@ -584,7 +598,7 @@
 
 #define HELP_mkdir "usage: mkdir [-vp] [-m MODE] [DIR...]\n\nCreate one or more directories.\n\n-m	Set permissions of directory to mode\n-p	Make parent directories as needed\n-v	Verbose"
 
-#define HELP_ls "usage: ls [-ACFHLRSZacdfhiklmnpqrstuwx1] [--color[=auto]] [FILE...]\n\nList files.\n\nwhat to show:\n-a  all files including .hidden    -b  escape nongraphic chars\n-c  use ctime for timestamps       -d  directory, not contents\n-i  inode number                   -p  put a '/' after dir names\n-q  unprintable chars as '?'       -s  storage used (1024 byte units)\n-u  use access time for timestamps -A  list all files but . and ..\n-H  follow command line symlinks   -L  follow symlinks\n-R  recursively list in subdirs    -F  append /dir *exe @sym |FIFO\n-Z  security context\n\noutput formats:\n-1  list one file per line         -C  columns (sorted vertically)\n-g  like -l but no owner           -h  human readable sizes\n-l  long (show full details)       -m  comma separated\n-n  like -l but numeric uid/gid    -o  like -l but no group\n-w  set column width               -x  columns (horizontal sort)\n-ll long with nanoseconds (--full-time)\n--color  device=yellow  symlink=turquoise/red  dir=blue  socket=purple\n         files: exe=green  suid=red  suidfile=redback  stickydir=greenback\n         =auto means detect if output is a tty.\n\nsorting (default is alphabetical):\n-f  unsorted    -r  reverse    -t  timestamp    -S  size"
+#define HELP_ls "usage: ls [-1ACFHLNRSUXZabcdfghilmnopqrstuwx] [--color[=auto]] [FILE...]\n\nList files\n\nwhat to show:\n-A  all files except . and ..      -a  all files including .hidden\n-b  escape nongraphic chars        -d  directory, not contents\n-F  append /dir *exe @sym |FIFO    -f  files (no sort/filter/format)\n-H  follow command line symlinks   -i  inode number\n-L  follow symlinks                -N  no escaping, even on tty\n-p  put '/' after dir names        -q  unprintable chars as '?'\n-R  recursively list in subdirs    -s  storage used (1024 byte units)\n-Z  security context\n\noutput formats:\n-1  list one file per line         -C  columns (sorted vertically)\n-g  like -l but no owner           -h  human readable sizes\n-l  long (show full details)       -ll long with nanoseconds (--full-time)\n-m  comma separated                -n  long with numeric uid/gid\n-o  long without group column      -r  reverse order\n-w  set column width               -x  columns (horizontal sort)\n\nsort by:  (also --sort=longname,longname... ends with alphabetical)\n-c  ctime      -r  reverse    -S  size     -t  time    -u  atime    -U  none\n-X  extension  -!  dirfirst   -~  nocase\n\n--color  =always (default)  =auto (when stdout is tty) =never\n    exe=green  suid=red  suidfile=redback  stickydir=greenback\n    device=yellow  symlink=turquoise/red  dir=blue  socket=purple\n\nLong output uses -cu for display, use -ltc/-ltu to also sort by ctime/atime."
 
 #define HELP_logger "usage: logger [-s] [-t TAG] [-p [FACILITY.]PRIORITY] [MESSAGE...]\n\nLog message (or stdin) to syslog.\n\n-s	Also write message to stderr\n-t	Use TAG instead of username to identify message source\n-p	Specify PRIORITY with optional FACILITY. Default is \"user.notice\""
 
@@ -614,7 +628,7 @@
 
 #define HELP_getconf "usage: getconf -a [PATH] | -l | NAME [PATH]\n\nGet system configuration values. Values from pathconf(3) require a path.\n\n-a	Show all (defaults to \"/\" if no path given)\n-l	List available value names (grouped by source)"
 
-#define HELP_find "usage: find [-HL] [DIR...] [<options>]\n\nSearch directories for matching files.\nDefault: search \".\", match all, -print matches.\n\n-H  Follow command line symlinks         -L  Follow all symlinks\n\nMatch filters:\n-name  PATTERN   filename with wildcards   -iname      ignore case -name\n-path  PATTERN   path name with wildcards  -ipath      ignore case -path\n-user  UNAME     belongs to user UNAME     -nouser     user ID not known\n-group GROUP     belongs to group GROUP    -nogroup    group ID not known\n-perm  [-/]MODE  permissions (-=min /=any) -prune      ignore dir contents\n-size  N[c]      512 byte blocks (c=bytes) -xdev       only this filesystem\n-links N         hardlink count            -atime N[u] accessed N units ago\n-ctime N[u]      created N units ago       -mtime N[u] modified N units ago\n-inum N          inode number N            -empty      empty files and dirs\n-true            always true               -false      always false\n-context PATTERN security context          -executable access(X_OK) perm+ACL\n-samefile FILE   hardlink to FILE          -quit       exit immediately\n-depth           ignore contents of dir    -maxdepth N at most N dirs down\n-newer FILE      newer mtime than FILE     -mindepth N at least N dirs down\n-newerXY FILE    X=acm time > FILE's Y=acm time (Y=t: FILE is literal time)\n-type [bcdflps]  type is (block, char, dir, file, symlink, pipe, socket)\n\nNumbers N may be prefixed by a - (less than) or + (greater than). Units for\n-Xtime are d (days, default), h (hours), m (minutes), or s (seconds).\n\nCombine matches with:\n!, -a, -o, ( )    not, and, or, group expressions\n\nActions:\n-print  Print match with newline  -print0        Print match with null\n-exec   Run command with path     -execdir       Run command in file's dir\n-ok     Ask before exec           -okdir         Ask before execdir\n-delete Remove matching file/dir  -printf FORMAT Print using format string\n\nCommands substitute \"{}\" with matched file. End with \";\" to run each file,\nor \"+\" (next argument after \"{}\") to collect and run with multiple files.\n\n-printf FORMAT characters are \\ escapes and:\n%b  512 byte blocks used\n%f  basename            %g  textual gid          %G  numeric gid\n%i  decimal inode       %l  target of symlink    %m  octal mode\n%M  ls format type/mode %p  path to file         %P  path to file minus DIR\n%s  size in bytes       %T@ mod time as unixtime\n%u  username            %U  numeric uid          %Z  security context"
+#define HELP_find "usage: find [-HL] [DIR...] [<options>]\n\nSearch directories for matching files.\nDefault: search \".\", match all, -print matches.\n\n-H  Follow command line symlinks         -L  Follow all symlinks\n\nMatch filters:\n-name  PATTERN   filename with wildcards   -iname      ignore case -name\n-path  PATTERN   path name with wildcards  -ipath      ignore case -path\n-user  UNAME     belongs to user UNAME     -nouser     user ID not known\n-group GROUP     belongs to group GROUP    -nogroup    group ID not known\n-perm  [-/]MODE  permissions (-=min /=any) -prune      ignore dir contents\n-size  N[c]      512 byte blocks (c=bytes) -xdev       only this filesystem\n-links N         hardlink count            -empty      empty files and dirs\n-atime N[u]      accessed N units ago      -true       always true\n-ctime N[u]      created N units ago       -false      always false\n-mtime N[u]      modified N units ago      -executable access(X_OK) perm+ACL\n-inum  N         inode number N            -readable   access(R_OK) perm+ACL\n-context PATTERN security context          -depth      contents before dir\n-samefile FILE   hardlink to FILE          -maxdepth N at most N dirs down\n-newer    FILE   newer mtime than FILE     -mindepth N at least N dirs down\n-newerXY  FILE   X=acm time > FILE's Y=acm time (Y=t: FILE is literal time)\n-type [bcdflps]  type is (block, char, dir, file, symlink, pipe, socket)\n\nNumbers N may be prefixed by - (less than) or + (greater than). Units for\n-[acm]time are d (days, default), h (hours), m (minutes), or s (seconds).\n\nCombine matches with:\n!, -a, -o, ( )    not, and, or, group expressions\n\nActions:\n-print  Print match with newline  -print0        Print match with null\n-exec   Run command with path     -execdir       Run command in file's dir\n-ok     Ask before exec           -okdir         Ask before execdir\n-delete Remove matching file/dir  -printf FORMAT Print using format string\n-quit   Exit immediately\n\nCommands substitute \"{}\" with matched file. End with \";\" to run each file,\nor \"+\" (next argument after \"{}\") to collect and run with multiple files.\n\n-printf FORMAT characters are \\ escapes and:\n%b  512 byte blocks used\n%f  basename            %g  textual gid          %G  numeric gid\n%i  decimal inode       %l  target of symlink    %m  octal mode\n%M  ls format type/mode %p  path to file         %P  path to file minus DIR\n%s  size in bytes       %T@ mod time as unixtime\n%u  username            %U  numeric uid          %Z  security context"
 
 #define HELP_file "usage: file [-bhLs] [FILE...]\n\nExamine the given files and describe their content types.\n\n-b	Brief (no filename)\n-h	Don't follow symlinks (default)\n-L	Follow symlinks\n-s	Show block/char device contents"
 
@@ -634,9 +648,9 @@
 
 #define HELP_date "usage: date [-u] [-I RES] [-r FILE] [-d DATE] [+DISPLAY_FORMAT] [-D SET_FORMAT] [SET]\n\nSet/get the current date/time. With no SET shows the current date.\n\n-d	Show DATE instead of current time (convert date format)\n-D	+FORMAT for SET or -d (instead of MMDDhhmm[[CC]YY][.ss])\n-I RES	ISO 8601 with RESolution d=date/h=hours/m=minutes/s=seconds/n=ns\n-r	Use modification time of FILE instead of current date\n-s DATE	Set the system clock to DATE.\n-u	Use UTC instead of current timezone\n\nSupported input formats:\n\nMMDDhhmm[[CC]YY][.ss]     POSIX\n@UNIXTIME[.FRACTION]      seconds since midnight 1970-01-01\nYYYY-MM-DD [hh:mm[:ss]]   ISO 8601\nhh:mm[:ss]                24-hour time today\n\nAll input formats can be followed by fractional seconds, and/or a UTC\noffset such as -0800.\n\nAll input formats can be preceded by TZ=\"id\" to set the input time zone\nseparately from the output time zone. Otherwise $TZ sets both.\n\n+FORMAT specifies display format string using strftime(3) syntax:\n\n%% literal %             %n newline              %t tab\n%S seconds (00-60)       %M minute (00-59)       %m month (01-12)\n%H hour (0-23)           %I hour (01-12)         %p AM/PM\n%y short year (00-99)    %Y year                 %C century\n%a short weekday name    %A weekday name         %u day of week (1-7, 1=mon)\n%b short month name      %B month name           %Z timezone name\n%j day of year (001-366) %d day of month (01-31) %e day of month ( 1-31)\n%N nanosec (output only)\n\n%U Week of year (0-53 start Sunday)   %W Week of year (0-53 start Monday)\n%V Week of year (1-53 start Monday, week < 4 days not part of this year)\n\n%F \"%Y-%m-%d\"   %R \"%H:%M\"        %T \"%H:%M:%S\"        %z  timezone (-0800)\n%D \"%m/%d/%y\"   %r \"%I:%M:%S %p\"  %h \"%b\"              %:z timezone (-08:00)\n%x locale date  %X locale time    %c locale date/time  %s  unix epoch time"
 
-#define HELP_cut "usage: cut [-Ds] [-bcCfF LIST] [-dO DELIM] [FILE...]\n\nPrint selected parts of lines from each FILE to standard output.\n\nEach selection LIST is comma separated, either numbers (counting from 1)\nor dash separated ranges (inclusive, with X- meaning to end of line and -X\nfrom start). By default selection ranges are sorted and collated, use -D\nto prevent that.\n\n-b	Select bytes\n-c	Select UTF-8 characters\n-C	Select unicode columns\n-d	Use DELIM (default is TAB for -f, run of whitespace for -F)\n-D	Don't sort/collate selections or match -fF lines without delimiter\n-f	Select fields (words) separated by single DELIM character\n-F	Select fields separated by DELIM regex\n-O	Output delimiter (default one space for -F, input delim for -f)\n-s	Skip lines without delimiters"
+#define HELP_cut "usage: cut [-Ds] [-bcCfF LIST] [-dO DELIM] [FILE...]\n\nPrint selected parts of lines from each FILE to standard output.\n\nEach selection LIST is comma separated, either numbers (counting from 1)\nor dash separated ranges (inclusive, with X- meaning to end of line and -X\nfrom start). By default selection ranges are sorted and collated, use -D\nto prevent that.\n\n-b	Select bytes (with -n round start/end down to start of utf8 char)\n-c	Select UTF-8 characters\n-C	Select unicode columns\n-d	Use DELIM (default is TAB for -f, run of whitespace for -F)\n-D	Don't sort/collate selections or match -fF lines without delimiter\n-f	Select fields (words) separated by single DELIM character\n-F	Select fields separated by DELIM regex\n-O	Output delimiter (default one space for -F, input delim for -f)\n-s	Skip lines without delimiters"
 
-#define HELP_cpio "usage: cpio -{o|t|i|p DEST} [-v] [--verbose] [-F FILE] [--no-preserve-owner]\n       [ignored: -m -H newc]\n\nCopy files into and out of a \"newc\" format cpio archive.\n\n-F FILE	Use archive FILE instead of stdin/stdout\n-p DEST	Copy-pass mode, copy stdin file list to directory DEST\n-i	Extract from archive into file system (stdin=archive)\n-o	Create archive (stdin=list of files, stdout=archive)\n-t	Test files (list only, stdin=archive, stdout=list of files)\n-d	Create directories if needed\n-u	unlink existing files when extracting\n-v	Verbose\n--no-preserve-owner (don't set ownership during extract)"
+#define HELP_cpio "usage: cpio -{o|t|i|p DEST} [-v] [--verbose] [-F FILE] [-R [USER][:GROUP] [--no-preserve-owner]\n\nCopy files into and out of a \"newc\" format cpio archive.\n\n-d	Create directories if needed\n-F FILE	Use archive FILE instead of stdin/stdout\n-i	Extract from archive into file system (stdin=archive)\n-o	Create archive (stdin=list of files, stdout=archive)\n-p DEST	Copy-pass mode, copy stdin file list to directory DEST\n-R USER	Replace owner with USER[:GROUP]\n-t	Test files (list only, stdin=archive, stdout=list of files)\n-u	Unlink existing files when extracting\n-v	Verbose\n--no-preserve-owner     Don't set ownership during extract"
 
 #define HELP_install "usage: install [-dDpsv] [-o USER] [-g GROUP] [-m MODE] [-t TARGET] [SOURCE...] [DEST]\n\nCopy files and set attributes.\n\n-d	Act like mkdir -p\n-D	Create leading directories for DEST\n-g	Make copy belong to GROUP\n-m	Set permissions to MODE\n-o	Make copy belong to USER\n-p	Preserve timestamps\n-s	Call \"strip -p\"\n-t	Copy files to TARGET dir (no DEST)\n-v	Verbose"
 
@@ -658,8 +672,6 @@
 
 #define HELP_chgrp "usage: chgrp/chown [-RHLP] [-fvh] GROUP FILE...\n\nChange group of one or more files.\n\n-f	Suppress most error messages\n-h	Change symlinks instead of what they point to\n-R	Recurse into subdirectories (implies -h)\n-H	With -R change target of symlink, follow command line symlinks\n-L	With -R change target of symlink, follow all symlinks\n-P	With -R change symlink, do not follow symlinks (default)\n-v	Verbose"
 
-#define HELP_catv "usage: catv [-evt] [FILE...]\n\nDisplay nonprinting characters as escape sequences. Use M-x for\nhigh ascii characters (>127), and ^x for other nonprinting chars.\n\n-e	Mark each newline with $\n-t	Show tabs as ^I\n-v	Don't use ^x or M-x escapes"
-
 #define HELP_cat "usage: cat [-etuv] [FILE...]\n\nCopy (concatenate) files to stdout.  If no files listed, copy from stdin.\nFilename \"-\" is a synonym for stdin.\n\n-e	Mark each newline with $\n-t	Show tabs as ^I\n-u	Copy one byte at a time (slow)\n-v	Display nonprinting characters as escape sequences with M-x for\n	high ascii characters (>127), and ^x for other nonprinting chars"
 
 #define HELP_cal "usage: cal [[[DAY] MONTH] YEAR]\n\nPrint a calendar.\n\nWith one argument, prints all months of the specified year.\nWith two arguments, prints calendar for month and year.\nWith three arguments, highlights day within month and year.\n\n-h	Don't highlight today"
diff --git a/android/linux/generated/newtoys.h b/android/linux/generated/newtoys.h
index ade8831..0680e5d 100644
--- a/android/linux/generated/newtoys.h
+++ b/android/linux/generated/newtoys.h
@@ -1,10 +1,11 @@
-USE_TOYBOX(NEWTOY(toybox, NULL, TOYFLAG_STAYROOT|TOYFLAG_NOHELP))
+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_ACPI(NEWTOY(acpi, "abctV", TOYFLAG_USR|TOYFLAG_BIN))
 USE_GROUPADD(OLDTOY(addgroup, groupadd, TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
 USE_USERADD(OLDTOY(adduser, useradd, TOYFLAG_NEEDROOT|TOYFLAG_UMASK|TOYFLAG_SBIN))
@@ -12,21 +13,20 @@
 USE_ARP(NEWTOY(arp, "vi:nDsdap:A:H:[+Ap][!sd]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_ARPING(NEWTOY(arping, "<1>1s:I:w#<0c#<0AUDbqf[+AU][+Df]", TOYFLAG_USR|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))
-USE_BASE64(NEWTOY(base64, "diw#<0=76[!dw]", TOYFLAG_USR|TOYFLAG_BIN))
+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_BC(NEWTOY(bc, "i(interactive)l(mathlib)q(quiet)s(standard)w(warn)", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
 USE_BLKDISCARD(NEWTOY(blkdiscard, "<1>1f(force)l(length)#<0o(offset)#<0s(secure)z(zeroout)[!sz]", TOYFLAG_BIN))
-USE_BLKID(NEWTOY(blkid, "ULs*[!LU]", TOYFLAG_BIN))
+USE_BLKID(NEWTOY(blkid, "ULo:s*[!LU]", TOYFLAG_BIN))
 USE_BLOCKDEV(NEWTOY(blockdev, "<1>1(setro)(setrw)(getro)(getss)(getbsz)(setbsz)#<0(getsz)(getsize)(getsize64)(getra)(setra)#<0(flushbufs)(rereadpt)",TOYFLAG_SBIN))
 USE_BOOTCHARTD(NEWTOY(bootchartd, 0, TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
 USE_BRCTL(NEWTOY(brctl, "<1", TOYFLAG_USR|TOYFLAG_SBIN))
 USE_BUNZIP2(NEWTOY(bunzip2, "cftkv", TOYFLAG_USR|TOYFLAG_BIN))
 USE_BZCAT(NEWTOY(bzcat, NULL, TOYFLAG_USR|TOYFLAG_BIN))
 USE_CAL(NEWTOY(cal, ">3h", TOYFLAG_USR|TOYFLAG_BIN))
-USE_CAT(NEWTOY(cat, "u"USE_CAT_V("vte"), TOYFLAG_BIN))
-USE_CATV(NEWTOY(catv, USE_CATV("vte"), TOYFLAG_USR|TOYFLAG_BIN))
+USE_CAT(NEWTOY(cat, "uvte", TOYFLAG_BIN))
 USE_SH(NEWTOY(cd, ">1LP[-LP]", TOYFLAG_NOFORK))
 USE_CHATTR(NEWTOY(chattr, "?p#v#R", TOYFLAG_BIN))
 USE_CHCON(NEWTOY(chcon, "<2hvR", TOYFLAG_USR|TOYFLAG_BIN))
@@ -36,19 +36,19 @@
 USE_CHROOT(NEWTOY(chroot, "^<1", TOYFLAG_USR|TOYFLAG_SBIN|TOYFLAG_ARGFAIL(125)))
 USE_CHRT(NEWTOY(chrt, "^mp#<0iRbrfo[!ibrfo]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_CHSH(NEWTOY(chsh, "s:", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
-USE_CHVT(NEWTOY(chvt, "<1", TOYFLAG_USR|TOYFLAG_BIN))
+USE_CHVT(NEWTOY(chvt, "<1>1", TOYFLAG_USR|TOYFLAG_BIN))
 USE_CKSUM(NEWTOY(cksum, "HIPLN", TOYFLAG_BIN))
 USE_CLEAR(NEWTOY(clear, NULL, TOYFLAG_USR|TOYFLAG_BIN))
 USE_CMP(NEWTOY(cmp, "<1>4ls(silent)(quiet)n#<1[!ls]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
 USE_COMM(NEWTOY(comm, "<2>2321", TOYFLAG_USR|TOYFLAG_BIN))
 USE_COUNT(NEWTOY(count, NULL, TOYFLAG_USR|TOYFLAG_BIN))
 USE_CP(NEWTOY(cp, "<1(preserve):;D(parents)RHLPprudaslvnF(remove-destination)fit:T[-HLPd][-niu][+Rr]", TOYFLAG_BIN))
-USE_CPIO(NEWTOY(cpio, "(ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]", TOYFLAG_BIN))
+USE_CPIO(NEWTOY(cpio, "(ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)R(owner):md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]", TOYFLAG_BIN))
 USE_CRC32(NEWTOY(crc32, 0, TOYFLAG_BIN))
 USE_CROND(NEWTOY(crond, "fbSl#<0=8d#<0L:c:[-bf][-LS][-ld]", TOYFLAG_USR|TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
 USE_CRONTAB(NEWTOY(crontab, "c:u:elr[!elr]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
-USE_CUT(NEWTOY(cut, "b*|c*|f*|F*|C*|O(output-delimiter):d:sDn[!cbfF]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_DATE(NEWTOY(date, "d:D:I(iso)(iso-8601):;r:s:u(utc)[!dr]", TOYFLAG_BIN))
+USE_CUT(NEWTOY(cut, "b*|c*|f*|F(regex-fields)*|C*|O(output-delimiter):d:sD(allow-duplicates)n[!cbfF]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_DATE(NEWTOY(date, "d:D:I(iso-8601):;r:s:u(utc)[!dr]", TOYFLAG_BIN))
 USE_DD(NEWTOY(dd, 0, TOYFLAG_USR|TOYFLAG_BIN))
 USE_DEALLOCVT(NEWTOY(deallocvt, ">1", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_NEEDROOT))
 USE_SH(NEWTOY(declare, "pAailunxr", TOYFLAG_NOFORK))
@@ -58,12 +58,12 @@
 USE_DEMO_NUMBER(NEWTOY(demo_number, "D#=3<3M#<0hcdbs", TOYFLAG_BIN))
 USE_DEMO_SCANKEY(NEWTOY(demo_scankey, 0, TOYFLAG_BIN))
 USE_DEMO_UTF8TOWC(NEWTOY(demo_utf8towc, 0, TOYFLAG_USR|TOYFLAG_BIN))
-USE_DEVMEM(NEWTOY(devmem, "<1>3", TOYFLAG_USR|TOYFLAG_BIN))
-USE_DF(NEWTOY(df, "HPkhit*a[-HPh]", TOYFLAG_SBIN))
+USE_DEVMEM(NEWTOY(devmem, "<1>3", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_DF(NEWTOY(df, "HPkhit*a[-HPh]", TOYFLAG_BIN))
 USE_DHCP(NEWTOY(dhcp, "V:H:F:x*r:O*A#<0=20T#<0=3t#<0=3s:p:i:SBRCaovqnbf", TOYFLAG_SBIN|TOYFLAG_ROOTONLY))
 USE_DHCP6(NEWTOY(dhcp6, "r:A#<0T#<0t#<0s:p:i:SRvqnbf", TOYFLAG_SBIN|TOYFLAG_ROOTONLY))
 USE_DHCPD(NEWTOY(dhcpd, ">1P#<0>65535fi:S46[!46]", TOYFLAG_SBIN|TOYFLAG_ROOTONLY))
-USE_DIFF(NEWTOY(diff, "<2>2(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)L(label)*S(starting-file):N(new-file)r(recursive)U(unified)#<0=3", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
+USE_DIFF(NEWTOY(diff, "<2>2(unchanged-line-format):;(old-line-format):;(new-line-format):;(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)S(starting-file):F(show-function-line):;L(label)*N(new-file)r(recursive)U(unified)#<0=3", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
 USE_DIRNAME(NEWTOY(dirname, "<1", TOYFLAG_USR|TOYFLAG_BIN))
 USE_DMESG(NEWTOY(dmesg, "w(follow)CSTtrs#<1n#c[!Ttr][!Cc][!Sw]", TOYFLAG_BIN))
 USE_DNSDOMAINNAME(NEWTOY(dnsdomainname, ">0", TOYFLAG_BIN))
@@ -80,12 +80,12 @@
 USE_EXPAND(NEWTOY(expand, "t*", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
 USE_SH(NEWTOY(export, "np", TOYFLAG_NOFORK))
 USE_EXPR(NEWTOY(expr, NULL, TOYFLAG_USR|TOYFLAG_BIN))
-USE_FACTOR(NEWTOY(factor, 0, TOYFLAG_USR|TOYFLAG_BIN))
+USE_FACTOR(NEWTOY(factor, "?hx", TOYFLAG_USR|TOYFLAG_BIN))
 USE_FALLOCATE(NEWTOY(fallocate, ">1l#|o#", TOYFLAG_USR|TOYFLAG_BIN))
 USE_FALSE(NEWTOY(false, NULL, TOYFLAG_BIN|TOYFLAG_NOHELP|TOYFLAG_MAYFORK))
 USE_FDISK(NEWTOY(fdisk, "C#<0H#<0S#<0b#<512ul", TOYFLAG_SBIN))
 USE_FGREP(OLDTOY(fgrep, grep, TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)|TOYFLAG_LINEBUF))
-USE_FILE(NEWTOY(file, "<1bhLs[!hL]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_FILE(NEWTOY(file, "<1b(brief)hLs[!hL]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_FIND(NEWTOY(find, "?^HL[-HL]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_FLOCK(NEWTOY(flock, "<1>1nsux[-sux]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_FMT(NEWTOY(fmt, "w#<0=75", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
@@ -103,17 +103,22 @@
 USE_GETFATTR(NEWTOY(getfattr, "(only-values)dhn:", TOYFLAG_USR|TOYFLAG_BIN))
 USE_GETOPT(NEWTOY(getopt, "^a(alternative)n:(name)o:(options)l*(long)(longoptions)Tu", TOYFLAG_USR|TOYFLAG_BIN))
 USE_GETTY(NEWTOY(getty, "<2t#<0H:I:l:f:iwnmLh", TOYFLAG_SBIN))
+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_GPIOINFO(NEWTOY(gpiofind, "<1>1", TOYFLAG_USR|TOYFLAG_BIN))
+USE_GPIOFIND(NEWTOY(gpiofind, "<1>1", TOYFLAG_USR|TOYFLAG_BIN))
 USE_GPIOGET(NEWTOY(gpioget, "<2l", TOYFLAG_USR|TOYFLAG_BIN))
-USE_GPIOFIND(NEWTOY(gpioinfo, 0, TOYFLAG_USR|TOYFLAG_BIN))
+USE_GPIOINFO(NEWTOY(gpioinfo, 0, TOYFLAG_USR|TOYFLAG_BIN))
 USE_GPIOSET(NEWTOY(gpioset, "<2l", 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)rRsvwcL(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_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_GROUPADD(NEWTOY(groupadd, "<1>2g#<0S", TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
 USE_GROUPDEL(NEWTOY(groupdel, "<1>2", TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
 USE_GROUPS(NEWTOY(groups, NULL, TOYFLAG_USR|TOYFLAG_BIN))
-USE_GUNZIP(NEWTOY(gunzip, "cdfk123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_GZIP(NEWTOY(gzip,    "ncdfk123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_GUNZIP(NEWTOY(gunzip, "cdfkt123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
+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))
@@ -124,18 +129,19 @@
 USE_HOST(NEWTOY(host, "<1>2avt:", TOYFLAG_USR|TOYFLAG_BIN))
 USE_HOSTID(NEWTOY(hostid, ">0", TOYFLAG_USR|TOYFLAG_BIN))
 USE_HOSTNAME(NEWTOY(hostname, ">1bdsfF:[!bdsf]", TOYFLAG_BIN))
+USE_HTTPD(NEWTOY(httpd, ">1v", TOYFLAG_USR|TOYFLAG_BIN))
 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_I2CDETECT(NEWTOY(i2cdetect, ">3aFlqry[!qr]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_I2CDUMP(NEWTOY(i2cdump, "<2>2fy", TOYFLAG_USR|TOYFLAG_BIN))
-USE_I2CGET(NEWTOY(i2cget, "<3>3fy", TOYFLAG_USR|TOYFLAG_BIN))
-USE_I2CSET(NEWTOY(i2cset, "<4fy", TOYFLAG_USR|TOYFLAG_BIN))
+USE_I2CDETECT(NEWTOY(i2cdetect, ">3aFlqry[!qr]", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_I2CDUMP(NEWTOY(i2cdump, "<2>2fy", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_I2CGET(NEWTOY(i2cget, "<2>3fy", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_I2CSET(NEWTOY(i2cset, "<4fy", TOYFLAG_USR|TOYFLAG_SBIN))
 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_INSMOD(NEWTOY(insmod, "<1", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
-USE_INSTALL(NEWTOY(install, "<1cdDpsvt:m:o:g:", TOYFLAG_USR|TOYFLAG_BIN))
+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))
 USE_IORENICE(NEWTOY(iorenice, "<1>3", TOYFLAG_USR|TOYFLAG_BIN))
 USE_IOTOP(NEWTOY(iotop, ">0AaKO" "Hk*o*p*u*s#<1=7d%<100=3000m#n#<1bq", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT|TOYFLAG_LOCALE))
@@ -163,11 +169,11 @@
 USE_LOGNAME(NEWTOY(logname, ">0", TOYFLAG_USR|TOYFLAG_BIN))
 USE_LOGPATH(NEWTOY(logpath, 0, TOYFLAG_NOHELP|TOYFLAG_USR|TOYFLAG_BIN))
 USE_LOSETUP(NEWTOY(losetup, ">2S(sizelimit)#s(show)ro#j:fdcaD[!afj]", TOYFLAG_SBIN))
-USE_LS(NEWTOY(ls, "(color):;(full-time)(show-control-chars)ZgoACFHLRSabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][!qb]", TOYFLAG_BIN|TOYFLAG_LOCALE))
+USE_LS(NEWTOY(ls, "(sort):(color):;(full-time)(show-control-chars)\241(group-directories-first)\376ZgoACFHLNRSUXabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][-Nqb]", TOYFLAG_BIN|TOYFLAG_LOCALE))
 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@i:", 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_MAN(NEWTOY(man, "k:M:", TOYFLAG_USR|TOYFLAG_BIN))
@@ -186,19 +192,21 @@
 USE_MODINFO(NEWTOY(modinfo, "<1b:k:F:0", TOYFLAG_SBIN))
 USE_MODPROBE(NEWTOY(modprobe, "alrqvsDbd*", TOYFLAG_SBIN))
 USE_MORE(NEWTOY(more, 0, TOYFLAG_USR|TOYFLAG_BIN))
-USE_MOUNT(NEWTOY(mount, "?O:afnrvwt:o*[-rw]", TOYFLAG_BIN|TOYFLAG_STAYROOT))
+USE_MOUNT(NEWTOY(mount, "?RO:afnrvwt:o*[-rw]", TOYFLAG_BIN|TOYFLAG_STAYROOT))
 USE_MOUNTPOINT(NEWTOY(mountpoint, "<1qdx[-dx]", TOYFLAG_BIN))
-USE_MV(NEWTOY(mv, "<1vnF(remove-destination)fit:T[-ni]", TOYFLAG_BIN))
+USE_MV(NEWTOY(mv, "<1v(verbose)nF(remove-destination)fit:T[-ni]", TOYFLAG_BIN))
 USE_NBD_CLIENT(OLDTOY(nbd-client, nbd_client, TOYFLAG_USR|TOYFLAG_BIN))
-USE_NBD_CLIENT(NEWTOY(nbd_client, "<3>3ns", 0))
+USE_NBD_SERVER(OLDTOY(nbd-server, nbd_server, TOYFLAG_USR|TOYFLAG_BIN))
+USE_NBD_CLIENT(NEWTOY(nbd_client, "<3>3b#<1>4294967295=4096ns", 0))
+USE_NBD_SERVER(NEWTOY(nbd_server, "<1>1r", 0))
 USE_NETCAT(OLDTOY(nc, netcat, TOYFLAG_USR|TOYFLAG_BIN))
-USE_NETCAT(NEWTOY(netcat, USE_NETCAT_LISTEN("^tElL")"w#<1W#<1p#<1>65535q#<1s:f:46uU"USE_NETCAT_LISTEN("[!tlL][!Lw]")"[!46U]", TOYFLAG_BIN))
+USE_NETCAT(NEWTOY(netcat, "^tElLw#<1W#<1p#<1>65535q#<1s:f:46uUn[!tlL][!Lw][!Lu][!46U]", TOYFLAG_BIN))
 USE_NETSTAT(NEWTOY(netstat, "pWrxwutneal", TOYFLAG_BIN))
 USE_NICE(NEWTOY(nice, "^<1n#", TOYFLAG_BIN))
 USE_NL(NEWTOY(nl, "v#=1l#w#<0=6b:n:s:E", TOYFLAG_USR|TOYFLAG_BIN))
 USE_NOHUP(NEWTOY(nohup, "<1^", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(125)))
 USE_NPROC(NEWTOY(nproc, "(all)", TOYFLAG_USR|TOYFLAG_BIN))
-USE_NSENTER(NEWTOY(nsenter, "<1F(no-fork)t#<1(target)i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user);", TOYFLAG_USR|TOYFLAG_BIN))
+USE_NSENTER(NEWTOY(nsenter, "<1a(all)F(no-fork)t#<1(target)C(cgroup):; i(ipc):; m(mount):; n(net):; p(pid):; u(uts):; U(user):; ", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
 USE_OD(NEWTOY(od, "j#vw#<1=16N#xsodcbA:t*", TOYFLAG_USR|TOYFLAG_BIN))
 USE_ONEIT(NEWTOY(oneit, "^<1nc:p3[!pn]", TOYFLAG_SBIN))
 USE_OPENVT(NEWTOY(openvt, "^<1c#<1>63sw", TOYFLAG_BIN|TOYFLAG_NEEDROOT))
@@ -223,21 +231,21 @@
 USE_PWGEN(NEWTOY(pwgen, ">2r(remove):c(capitalize)n(numerals)y(symbols)s(secure)B(ambiguous)h(help)C1vA(no-capitalize)0(no-numerals)[-cA][-n0][-C1]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_READAHEAD(NEWTOY(readahead, NULL, TOYFLAG_BIN))
 USE_READELF(NEWTOY(readelf, "<1(dyn-syms)adehlnp:SsWx:", TOYFLAG_USR|TOYFLAG_BIN))
-USE_READLINK(NEWTOY(readlink, "<1nqmef(canonicalize)[-mef]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_REALPATH(OLDTOY(realpath, readlink, TOYFLAG_USR|TOYFLAG_BIN))
+USE_READLINK(NEWTOY(readlink, "<1vnf(canonicalize)emqz[-mef][-qv]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_REALPATH(NEWTOY(realpath, "<1(relative-base):R(relative-to):s(no-symlinks)LPemqz[-Ps][-LP][-me]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_REBOOT(NEWTOY(reboot, "d:fn", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
 USE_RENICE(NEWTOY(renice, "<1gpun#|", TOYFLAG_USR|TOYFLAG_BIN))
 USE_RESET(NEWTOY(reset, 0, TOYFLAG_USR|TOYFLAG_BIN))
 USE_RESTORECON(NEWTOY(restorecon, "<1DFnRrv", TOYFLAG_USR|TOYFLAG_SBIN))
 USE_REV(NEWTOY(rev, NULL, TOYFLAG_USR|TOYFLAG_BIN))
 USE_RFKILL(NEWTOY(rfkill, "<1>2", TOYFLAG_USR|TOYFLAG_SBIN))
-USE_RM(NEWTOY(rm, "fiRrv[-fi]", 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_ROUTE(NEWTOY(route, "?neA:", TOYFLAG_SBIN))
 USE_RTCWAKE(NEWTOY(rtcwake, "(list-modes);(auto)a(device)d:(local)l(mode)m:(seconds)s#(time)t#(utc)u(verbose)v[!alu]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_RUNCON(NEWTOY(runcon, "<2", TOYFLAG_USR|TOYFLAG_SBIN))
-USE_SED(NEWTOY(sed, "(help)(version)e*f*i:;nErz(null-data)s[+Er]", TOYFLAG_BIN|TOYFLAG_LOCALE|TOYFLAG_NOHELP))
+USE_RUNCON(NEWTOY(runcon, "^<2", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_SED(NEWTOY(sed, "(help)(version)(tarxform)e*f*i:;nErz(null-data)s[+Er]", TOYFLAG_BIN|TOYFLAG_LOCALE|TOYFLAG_NOHELP))
 USE_SENDEVENT(NEWTOY(sendevent, "<4>4", TOYFLAG_USR|TOYFLAG_SBIN))
 USE_SEQ(NEWTOY(seq, "<1>3?f:s:w[!fw]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_SH(NEWTOY(set, 0, TOYFLAG_NOFORK))
@@ -253,11 +261,12 @@
 USE_SHA512SUM(OLDTOY(sha512sum, md5sum, TOYFLAG_USR|TOYFLAG_BIN))
 USE_SH(NEWTOY(shift, ">1", TOYFLAG_NOFORK))
 USE_SHRED(NEWTOY(shred, "<1zxus#<1n#<1o#<0f", TOYFLAG_USR|TOYFLAG_BIN))
-USE_SKELETON(NEWTOY(skeleton, "(walrus)(blubber):;(also):e@d*c#b:a", TOYFLAG_USR|TOYFLAG_BIN))
+USE_SHUF(NEWTOY(shuf, "zen#<0", TOYFLAG_USR|TOYFLAG_BIN))
+USE_SKELETON(NEWTOY(skeleton, "(walrus)(blubber):;(also):h(hlong):; g(glong): f(longf):;e@d*c#b:a", TOYFLAG_USR|TOYFLAG_BIN))
 USE_SKELETON_ALIAS(NEWTOY(skeleton_alias, "b#dq", TOYFLAG_USR|TOYFLAG_BIN))
 USE_SLEEP(NEWTOY(sleep, "<1", TOYFLAG_BIN))
 USE_SNTP(NEWTOY(sntp, ">1M :m :Sp:t#<0=1>16asdDqr#<4>17=10[!as]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_SORT(NEWTOY(sort, USE_SORT_FLOAT("g")"S:T:m" "o:k*t:" "xVbMcszdfirun", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
+USE_SORT(NEWTOY(sort, USE_SORT_FLOAT("g")"S:T:m" "o:k*t:" "xVbMCcszdfirun", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
 USE_SH(NEWTOY(source, "<1", TOYFLAG_NOFORK))
 USE_SPLIT(NEWTOY(split, ">2a#<1=2>9b#<1l#<1n#<1[!bl][!bn][!ln]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_STAT(NEWTOY(stat, "<1c:(format)fLt", TOYFLAG_BIN))
@@ -266,7 +275,7 @@
 USE_STTY(NEWTOY(stty, "?aF:g[!ag]", TOYFLAG_BIN))
 USE_SU(NEWTOY(su, "^lmpu:g:c:s:[!lmp]", TOYFLAG_BIN|TOYFLAG_ROOTONLY))
 USE_SULOGIN(NEWTOY(sulogin, "t#<0=0", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
-USE_SWAPOFF(NEWTOY(swapoff, "<1>1", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
+USE_SWAPOFF(NEWTOY(swapoff, "<1>1av", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
 USE_SWAPON(NEWTOY(swapon, "<1>1p#<0>32767d", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
 USE_SWITCH_ROOT(NEWTOY(switch_root, "<2c:h", TOYFLAG_SBIN))
 USE_SYNC(NEWTOY(sync, NULL, TOYFLAG_BIN))
@@ -274,9 +283,9 @@
 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_TAC(NEWTOY(tac, NULL, TOYFLAG_USR|TOYFLAG_BIN))
 USE_TAIL(NEWTOY(tail, "?fFs:c(bytes)-n(lines)-[-cn][-fF]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_TAR(NEWTOY(tar, "&(strip-components)#(selinux)(restrict)(full-time)(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mode):(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)I(use-compress-program):J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):a[!txc][!jzJa]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_TASKSET(NEWTOY(taskset, "<1^pa", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
-USE_TCPSVD(NEWTOY(tcpsvd, "^<3c#=30<1C:b#=20<0u:l:hEv", TOYFLAG_USR|TOYFLAG_BIN))
+USE_TAR(NEWTOY(tar, "&(no-ignore-case)(ignore-case)(no-anchored)(anchored)(no-wildcards)(wildcards)(no-wildcards-match-slash)(wildcards-match-slash)(show-transformed-names)(selinux)(restrict)(full-time)(no-recursion)(null)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(sort);:(mode):(mtime):(group):(owner):(to-command):~(strip-components)(strip)#~(transform)(xform)*o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*I(use-compress-program):C(directory):f(file):as[!txc][!jzJa]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_TASKSET(NEWTOY(taskset, "<1^pa", TOYFLAG_USR|TOYFLAG_BIN))
+USE_TCPSVD(NEWTOY(tcpsvd, "^<3c#=30<1b#=20<0C:u:l:hEv", 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))
@@ -284,7 +293,7 @@
 USE_TFTP(NEWTOY(tftp, "<1b#<8>65464r:l:g|p|[!gp]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_TFTPD(NEWTOY(tftpd, "rcu:l", TOYFLAG_BIN))
 USE_TIME(NEWTOY(time, "<1^pv[-pv]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_MAYFORK))
-USE_TIMEOUT(NEWTOY(timeout, "<2^(foreground)(preserve-status)vk:s(signal):", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(125)))
+USE_TIMEOUT(NEWTOY(timeout, "<2^(foreground)(preserve-status)vk:s(signal):i", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(125)))
 USE_TOP(NEWTOY(top, ">0O*h" "Hk*o*p*u*s#<1d%<100=3000m#n#<1bq[!oO]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
 USE_TOUCH(NEWTOY(touch, "<1acd:fmr:t:h[!dtr]", TOYFLAG_BIN))
 USE_SH(OLDTOY(toysh, sh, TOYFLAG_BIN))
@@ -299,17 +308,17 @@
 USE_TCPSVD(OLDTOY(udpsvd, tcpsvd, TOYFLAG_USR|TOYFLAG_BIN))
 USE_ULIMIT(NEWTOY(ulimit, ">1P#<1SHavutsrRqpnmlifedc[-SH][!apvutsrRqnmlifedc]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_UMOUNT(NEWTOY(umount, "cndDflrat*v[!na]", TOYFLAG_BIN|TOYFLAG_STAYROOT))
-USE_UNAME(NEWTOY(uname, "aomvrns", TOYFLAG_BIN))
+USE_UNAME(NEWTOY(uname, "paomvrns", TOYFLAG_BIN))
 USE_UNICODE(NEWTOY(unicode, "<1", TOYFLAG_USR|TOYFLAG_BIN))
 USE_UNIQ(NEWTOY(uniq, "f#s#w#zicdu", TOYFLAG_USR|TOYFLAG_BIN))
 USE_UNIX2DOS(NEWTOY(unix2dos, 0, TOYFLAG_BIN))
 USE_UNLINK(NEWTOY(unlink, "<1>1", TOYFLAG_USR|TOYFLAG_BIN))
 USE_SH(NEWTOY(unset, "fvn[!fv]", TOYFLAG_NOFORK))
-USE_UNSHARE(NEWTOY(unshare, "<1^f(fork);r(map-root-user);i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user);", TOYFLAG_USR|TOYFLAG_BIN))
+USE_UNSHARE(NEWTOY(unshare, "<1^a(all)f(fork)r(map-root-user)C(cgroup):; i(ipc):; m(mount):; n(net):; p(pid):; u(uts):; U(user):; ", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
 USE_UPTIME(NEWTOY(uptime, ">0ps", TOYFLAG_USR|TOYFLAG_BIN))
 USE_USERADD(NEWTOY(useradd, "<1>2u#<0G:s:g:h:SDH", TOYFLAG_NEEDROOT|TOYFLAG_UMASK|TOYFLAG_SBIN))
 USE_USERDEL(NEWTOY(userdel, "<1>1r", TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
-USE_USLEEP(NEWTOY(usleep, "<1", TOYFLAG_BIN))
+USE_USLEEP(NEWTOY(usleep, "<1>1", TOYFLAG_BIN))
 USE_UUDECODE(NEWTOY(uudecode, ">1o:", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_UMASK))
 USE_UUENCODE(NEWTOY(uuencode, "<1>2m", TOYFLAG_USR|TOYFLAG_BIN))
 USE_UUIDGEN(NEWTOY(uuidgen, ">0r(random)", TOYFLAG_USR|TOYFLAG_BIN))
@@ -319,14 +328,14 @@
 USE_W(NEWTOY(w, NULL, TOYFLAG_USR|TOYFLAG_BIN))
 USE_SH(NEWTOY(wait, "n", TOYFLAG_NOFORK))
 USE_WATCH(NEWTOY(watch, "^<1n%<100=2000tebx", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
-USE_WATCHDOG(NEWTOY(watchdog, "<1>1Ft#=4<1T#=60<1", TOYFLAG_NEEDROOT|TOYFLAG_BIN))
+USE_WATCHDOG(NEWTOY(watchdog, "<1>1Ft#=4<1T#=60<1", TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
 USE_WC(NEWTOY(wc, "mcwl", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
 USE_WGET(NEWTOY(wget, "<1>1(max-redirect)#<0=20d(debug)O(output-document):p(post-data):", TOYFLAG_USR|TOYFLAG_BIN))
 USE_WHICH(NEWTOY(which, "<1a", TOYFLAG_USR|TOYFLAG_BIN))
 USE_WHO(NEWTOY(who, "a", TOYFLAG_USR|TOYFLAG_BIN))
 USE_WHOAMI(OLDTOY(whoami, logname, TOYFLAG_USR|TOYFLAG_BIN))
-USE_XARGS(NEWTOY(xargs, "^E:P#<0=1optrn#<1(max-args)s#0[!0E]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_XXD(NEWTOY(xxd, ">1c#<0>256l#o#g#<1=2iprs#[!rs]", 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_XXD(NEWTOY(xxd, ">1c#<0>256l#o#g#<0=2eiprs#[!rs][!re]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_XZCAT(NEWTOY(xzcat, NULL, TOYFLAG_USR|TOYFLAG_BIN))
 USE_YES(NEWTOY(yes, NULL, TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
-USE_ZCAT(NEWTOY(zcat,     "cdfk123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_ZCAT(NEWTOY(zcat,     "cdfkt123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
diff --git a/android/mac/generated/config.h b/android/mac/generated/config.h
index a9f4bdf..bd4c09b 100644
--- a/android/mac/generated/config.h
+++ b/android/mac/generated/config.h
@@ -1,61 +1,35 @@
-#define CFG_TOYBOX_ANDROID_SCHEDPOLICY 0
-#define USE_TOYBOX_ANDROID_SCHEDPOLICY(...)
-#define CFG_TOYBOX_CONTAINER 0
-#define USE_TOYBOX_CONTAINER(...)
-#define CFG_TOYBOX_COPYFILERANGE 0
-#define USE_TOYBOX_COPYFILERANGE(...)
+#define CFG_TOYBOX 1
+#define USE_TOYBOX(...) __VA_ARGS__
 #define CFG_TOYBOX_DEBUG 0
 #define USE_TOYBOX_DEBUG(...)
-#define CFG_TOYBOX_FALLOCATE 0
-#define USE_TOYBOX_FALLOCATE(...)
-#define CFG_TOYBOX_FIFREEZE 0
-#define USE_TOYBOX_FIFREEZE(...)
 #define CFG_TOYBOX_FLOAT 1
 #define USE_TOYBOX_FLOAT(...) __VA_ARGS__
 #define CFG_TOYBOX_FORK 1
 #define USE_TOYBOX_FORK(...) __VA_ARGS__
 #define CFG_TOYBOX_FREE 0
 #define USE_TOYBOX_FREE(...)
-#define CFG_TOYBOX_GETRANDOM 0
-#define USE_TOYBOX_GETRANDOM(...)
 #define CFG_TOYBOX_HELP_DASHDASH 1
 #define USE_TOYBOX_HELP_DASHDASH(...) __VA_ARGS__
 #define CFG_TOYBOX_HELP 1
 #define USE_TOYBOX_HELP(...) __VA_ARGS__
-#define CFG_TOYBOX_I18N 1
-#define USE_TOYBOX_I18N(...) __VA_ARGS__
-#define CFG_TOYBOX_ICONV 1
-#define USE_TOYBOX_ICONV(...) __VA_ARGS__
 #define CFG_TOYBOX_LIBCRYPTO 1
 #define USE_TOYBOX_LIBCRYPTO(...) __VA_ARGS__
 #define CFG_TOYBOX_LIBZ 1
 #define USE_TOYBOX_LIBZ(...) __VA_ARGS__
 #define CFG_TOYBOX_LSM_NONE 1
 #define USE_TOYBOX_LSM_NONE(...) __VA_ARGS__
-#define CFG_TOYBOX_MUSL_NOMMU_IS_BROKEN 0
-#define USE_TOYBOX_MUSL_NOMMU_IS_BROKEN(...)
-#define CFG_TOYBOX_NORECURSE 0
-#define USE_TOYBOX_NORECURSE(...)
+#define CFG_TOYBOX_NORECURSE 1
+#define USE_TOYBOX_NORECURSE(...) __VA_ARGS__
 #define CFG_TOYBOX_ON_ANDROID 0
 #define USE_TOYBOX_ON_ANDROID(...)
-#define CFG_TOYBOX_PEDANTIC_ARGS 0
-#define USE_TOYBOX_PEDANTIC_ARGS(...)
-#define CFG_TOYBOX_PRLIMIT 0
-#define USE_TOYBOX_PRLIMIT(...)
 #define CFG_TOYBOX_SELINUX 0
 #define USE_TOYBOX_SELINUX(...)
-#define CFG_TOYBOX_SHADOW 0
-#define USE_TOYBOX_SHADOW(...)
 #define CFG_TOYBOX_SMACK 0
 #define USE_TOYBOX_SMACK(...)
-#define CFG_TOYBOX_SUID 1
-#define USE_TOYBOX_SUID(...) __VA_ARGS__
+#define CFG_TOYBOX_SUID 0
+#define USE_TOYBOX_SUID(...)
 #define CFG_TOYBOX_UID_SYS 100
 #define CFG_TOYBOX_UID_USR 500
-#define CFG_TOYBOX_UTMPX 0
-#define USE_TOYBOX_UTMPX(...)
-#define CFG_TOYBOX 1
-#define USE_TOYBOX(...) __VA_ARGS__
 #define CFG_ACPI 0
 #define USE_ACPI(...)
 #define CFG_ARCH 0
@@ -90,10 +64,6 @@
 #define USE_BZCAT(...)
 #define CFG_CAL 0
 #define USE_CAL(...)
-#define CFG_CATV 0
-#define USE_CATV(...)
-#define CFG_CAT_V 1
-#define USE_CAT_V(...) __VA_ARGS__
 #define CFG_CAT 1
 #define USE_CAT(...) __VA_ARGS__
 #define CFG_CD 0
@@ -128,8 +98,6 @@
 #define USE_COUNT(...)
 #define CFG_CPIO 1
 #define USE_CPIO(...) __VA_ARGS__
-#define CFG_CP_PRESERVE 1
-#define USE_CP_PRESERVE(...) __VA_ARGS__
 #define CFG_CP 1
 #define USE_CP(...) __VA_ARGS__
 #define CFG_CRC32 0
@@ -204,8 +172,8 @@
 #define USE_FDISK(...)
 #define CFG_FGREP 1
 #define USE_FGREP(...) __VA_ARGS__
-#define CFG_FILE 0
-#define USE_FILE(...)
+#define CFG_FILE 1
+#define USE_FILE(...) __VA_ARGS__
 #define CFG_FIND 1
 #define USE_FIND(...) __VA_ARGS__
 #define CFG_FLOCK 0
@@ -240,6 +208,18 @@
 #define USE_GETOPT(...) __VA_ARGS__
 #define CFG_GETTY 0
 #define USE_GETTY(...)
+#define CFG_GITCHECKOUT 0
+#define USE_GITCHECKOUT(...)
+#define CFG_GITCLONE 0
+#define USE_GITCLONE(...)
+#define CFG_GITCOMPAT 0
+#define USE_GITCOMPAT(...)
+#define CFG_GITFETCH 0
+#define USE_GITFETCH(...)
+#define CFG_GITINIT 0
+#define USE_GITINIT(...)
+#define CFG_GITREMOTE 0
+#define USE_GITREMOTE(...)
 #define CFG_GPIODETECT 0
 #define USE_GPIODETECT(...)
 #define CFG_GPIOFIND 0
@@ -266,8 +246,6 @@
 #define USE_HEAD(...) __VA_ARGS__
 #define CFG_HELLO 0
 #define USE_HELLO(...)
-#define CFG_HELP_EXTRAS 0
-#define USE_HELP_EXTRAS(...)
 #define CFG_HELP 0
 #define USE_HELP(...)
 #define CFG_HEXDUMP 0
@@ -282,6 +260,8 @@
 #define USE_HOST(...)
 #define CFG_HOSTNAME 1
 #define USE_HOSTNAME(...) __VA_ARGS__
+#define CFG_HTTPD 0
+#define USE_HTTPD(...)
 #define CFG_HWCLOCK 0
 #define USE_HWCLOCK(...)
 #define CFG_I2CDETECT 0
@@ -350,8 +330,6 @@
 #define USE_LOGNAME(...)
 #define CFG_LOGPATH 0
 #define USE_LOGPATH(...)
-#define CFG_LOGWRAPPER 0
-#define USE_LOGWRAPPER(...)
 #define CFG_LOSETUP 0
 #define USE_LOSETUP(...)
 #define CFG_LSATTR 0
@@ -362,8 +340,6 @@
 #define USE_LSOF(...)
 #define CFG_LSPCI 0
 #define USE_LSPCI(...)
-#define CFG_LSPCI_TEXT 0
-#define USE_LSPCI_TEXT(...)
 #define CFG_LSUSB 0
 #define USE_LSUSB(...)
 #define CFG_LS 1
@@ -426,10 +402,10 @@
 #define USE_MV(...) __VA_ARGS__
 #define CFG_NBD_CLIENT 0
 #define USE_NBD_CLIENT(...)
+#define CFG_NBD_SERVER 0
+#define USE_NBD_SERVER(...)
 #define CFG_NETCAT 0
 #define USE_NETCAT(...)
-#define CFG_NETCAT_LISTEN 0
-#define USE_NETCAT_LISTEN(...)
 #define CFG_NETSTAT 0
 #define USE_NETSTAT(...)
 #define CFG_NICE 0
@@ -542,6 +518,8 @@
 #define USE_SH(...)
 #define CFG_SHRED 0
 #define USE_SHRED(...)
+#define CFG_SHUF 0
+#define USE_SHUF(...)
 #define CFG_SKELETON_ALIAS 0
 #define USE_SKELETON_ALIAS(...)
 #define CFG_SKELETON 0
@@ -678,8 +656,6 @@
 #define USE_WHO(...)
 #define CFG_W 0
 #define USE_W(...)
-#define CFG_XARGS_PEDANTIC 0
-#define USE_XARGS_PEDANTIC(...)
 #define CFG_XARGS 1
 #define USE_XARGS(...) __VA_ARGS__
 #define CFG_XXD 1
diff --git a/android/mac/generated/flags.h b/android/mac/generated/flags.h
index 516ffc7..0cb1833 100644
--- a/android/mac/generated/flags.h
+++ b/android/mac/generated/flags.h
@@ -1,11 +1,8 @@
 #undef FORCED_FLAG
-#undef FORCED_FLAGLL
 #ifdef FORCE_FLAGS
-#define FORCED_FLAG 1
-#define FORCED_FLAGLL 1ULL
+#define FORCED_FLAG 1LL
 #else
-#define FORCED_FLAG 0
-#define FORCED_FLAGLL 0LL
+#define FORCED_FLAG 0LL
 #endif
 
 // acpi   abctV
@@ -131,13 +128,14 @@
 #undef FLAG_f
 #endif
 
-// blkid   ULs*[!LU]
+// blkid   ULo:s*[!LU]
 #undef OPTSTR_blkid
-#define OPTSTR_blkid "ULs*[!LU]"
+#define OPTSTR_blkid "ULo:s*[!LU]"
 #ifdef CLEANUP_blkid
 #undef CLEANUP_blkid
 #undef FOR_blkid
 #undef FLAG_s
+#undef FLAG_o
 #undef FLAG_L
 #undef FLAG_U
 #endif
@@ -221,17 +219,6 @@
 #undef FLAG_u
 #endif
 
-// catv   vte
-#undef OPTSTR_catv
-#define OPTSTR_catv "vte"
-#ifdef CLEANUP_catv
-#undef CLEANUP_catv
-#undef FOR_catv
-#undef FLAG_e
-#undef FLAG_t
-#undef FLAG_v
-#endif
-
 // cd   >1LP[-LP]
 #undef OPTSTR_cd
 #define OPTSTR_cd ">1LP[-LP]"
@@ -323,9 +310,9 @@
 #undef FLAG_s
 #endif
 
-// chvt   <1
+// chvt   <1>1
 #undef OPTSTR_chvt
-#define OPTSTR_chvt "<1"
+#define OPTSTR_chvt "<1>1"
 #ifdef CLEANUP_chvt
 #undef CLEANUP_chvt
 #undef FOR_chvt
@@ -410,9 +397,9 @@
 #undef FLAG_preserve
 #endif
 
-// cpio (ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF] (ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]
+// cpio (ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)R(owner):md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF] (ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)R(owner):md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]
 #undef OPTSTR_cpio
-#define OPTSTR_cpio "(ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]"
+#define OPTSTR_cpio "(ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)R(owner):md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]"
 #ifdef CLEANUP_cpio
 #undef CLEANUP_cpio
 #undef FOR_cpio
@@ -426,6 +413,7 @@
 #undef FLAG_u
 #undef FLAG_d
 #undef FLAG_m
+#undef FLAG_R
 #undef FLAG_no_preserve_owner
 #undef FLAG_quiet
 #undef FLAG_renumber_inodes
@@ -468,9 +456,9 @@
 #undef FLAG_c
 #endif
 
-// cut b*|c*|f*|F*|C*|O(output-delimiter):d:sDn[!cbfF] b*|c*|f*|F*|C*|O(output-delimiter):d:sDn[!cbfF]
+// cut b*|c*|f*|F(regex-fields)*|C*|O(output-delimiter):d:sD(allow-duplicates)n[!cbfF] b*|c*|f*|F(regex-fields)*|C*|O(output-delimiter):d:sD(allow-duplicates)n[!cbfF]
 #undef OPTSTR_cut
-#define OPTSTR_cut "b*|c*|f*|F*|C*|O(output-delimiter):d:sDn[!cbfF]"
+#define OPTSTR_cut "b*|c*|f*|F(regex-fields)*|C*|O(output-delimiter):d:sD(allow-duplicates)n[!cbfF]"
 #ifdef CLEANUP_cut
 #undef CLEANUP_cut
 #undef FOR_cut
@@ -486,9 +474,9 @@
 #undef FLAG_b
 #endif
 
-// date d:D:I(iso)(iso-8601):;r:s:u(utc)[!dr] d:D:I(iso)(iso-8601):;r:s:u(utc)[!dr]
+// date d:D:I(iso-8601):;r:s:u(utc)[!dr] d:D:I(iso-8601):;r:s:u(utc)[!dr]
 #undef OPTSTR_date
-#define OPTSTR_date "d:D:I(iso)(iso-8601):;r:s:u(utc)[!dr]"
+#define OPTSTR_date "d:D:I(iso-8601):;r:s:u(utc)[!dr]"
 #ifdef CLEANUP_date
 #undef CLEANUP_date
 #undef FOR_date
@@ -714,17 +702,18 @@
 #undef FLAG_P
 #endif
 
-// diff <2>2(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)L(label)*S(starting-file):N(new-file)r(recursive)U(unified)#<0=3 <2>2(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)L(label)*S(starting-file):N(new-file)r(recursive)U(unified)#<0=3
+// diff <2>2(unchanged-line-format):;(old-line-format):;(new-line-format):;(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)S(starting-file):F(show-function-line):;L(label)*N(new-file)r(recursive)U(unified)#<0=3 <2>2(unchanged-line-format):;(old-line-format):;(new-line-format):;(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)S(starting-file):F(show-function-line):;L(label)*N(new-file)r(recursive)U(unified)#<0=3
 #undef OPTSTR_diff
-#define OPTSTR_diff "<2>2(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)L(label)*S(starting-file):N(new-file)r(recursive)U(unified)#<0=3"
+#define OPTSTR_diff "<2>2(unchanged-line-format):;(old-line-format):;(new-line-format):;(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)S(starting-file):F(show-function-line):;L(label)*N(new-file)r(recursive)U(unified)#<0=3"
 #ifdef CLEANUP_diff
 #undef CLEANUP_diff
 #undef FOR_diff
 #undef FLAG_U
 #undef FLAG_r
 #undef FLAG_N
-#undef FLAG_S
 #undef FLAG_L
+#undef FLAG_F
+#undef FLAG_S
 #undef FLAG_a
 #undef FLAG_q
 #undef FLAG_s
@@ -738,6 +727,9 @@
 #undef FLAG_B
 #undef FLAG_strip_trailing_cr
 #undef FLAG_color
+#undef FLAG_new_line_format
+#undef FLAG_old_line_format
+#undef FLAG_unchanged_line_format
 #endif
 
 // dirname <1 <1
@@ -900,12 +892,14 @@
 #undef FOR_expr
 #endif
 
-// factor    
+// factor   ?hx
 #undef OPTSTR_factor
-#define OPTSTR_factor 0
+#define OPTSTR_factor "?hx"
 #ifdef CLEANUP_factor
 #undef CLEANUP_factor
 #undef FOR_factor
+#undef FLAG_x
+#undef FLAG_h
 #endif
 
 // fallocate   >1l#|o#
@@ -940,9 +934,9 @@
 #undef FLAG_C
 #endif
 
-// file   <1bhLs[!hL]
+// file <1b(brief)hLs[!hL] <1b(brief)hLs[!hL]
 #undef OPTSTR_file
-#define OPTSTR_file "<1bhLs[!hL]"
+#define OPTSTR_file "<1b(brief)hLs[!hL]"
 #ifdef CLEANUP_file
 #undef CLEANUP_file
 #undef FOR_file
@@ -1144,6 +1138,46 @@
 #undef FLAG_t
 #endif
 
+// gitcheckout   <1
+#undef OPTSTR_gitcheckout
+#define OPTSTR_gitcheckout "<1"
+#ifdef CLEANUP_gitcheckout
+#undef CLEANUP_gitcheckout
+#undef FOR_gitcheckout
+#endif
+
+// gitclone   <1
+#undef OPTSTR_gitclone
+#define OPTSTR_gitclone "<1"
+#ifdef CLEANUP_gitclone
+#undef CLEANUP_gitclone
+#undef FOR_gitclone
+#endif
+
+// gitfetch    
+#undef OPTSTR_gitfetch
+#define OPTSTR_gitfetch 0
+#ifdef CLEANUP_gitfetch
+#undef CLEANUP_gitfetch
+#undef FOR_gitfetch
+#endif
+
+// gitinit   <1
+#undef OPTSTR_gitinit
+#define OPTSTR_gitinit "<1"
+#ifdef CLEANUP_gitinit
+#undef CLEANUP_gitinit
+#undef FOR_gitinit
+#endif
+
+// gitremote   <1
+#undef OPTSTR_gitremote
+#define OPTSTR_gitremote "<1"
+#ifdef CLEANUP_gitremote
+#undef CLEANUP_gitremote
+#undef FOR_gitremote
+#endif
+
 // gpiodetect   >0
 #undef OPTSTR_gpiodetect
 #define OPTSTR_gpiodetect ">0"
@@ -1186,9 +1220,9 @@
 #undef FLAG_l
 #endif
 
-// grep (line-buffered)(color):;(exclude-dir)*S(exclude)*M(include)*ZzEFHIab(byte-offset)h(no-filename)ino(only-matching)rRsvwcL(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)rRsvwcL(files-without-match)l(files-with-matches)q(quiet)(silent)e*f*C#B#A#m#x[!wx][!EF]
+// 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)rRsvwcL(files-without-match)l(files-with-matches)q(quiet)(silent)e*f*C#B#A#m#x[!wx][!EF]"
+#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
@@ -1253,9 +1287,9 @@
 #undef FOR_groups
 #endif
 
-// gunzip   cdfk123456789[-123456789]
+// gunzip   cdfkt123456789[-123456789]
 #undef OPTSTR_gunzip
-#define OPTSTR_gunzip "cdfk123456789[-123456789]"
+#define OPTSTR_gunzip "cdfkt123456789[-123456789]"
 #ifdef CLEANUP_gunzip
 #undef CLEANUP_gunzip
 #undef FOR_gunzip
@@ -1268,15 +1302,16 @@
 #undef FLAG_3
 #undef FLAG_2
 #undef FLAG_1
+#undef FLAG_t
 #undef FLAG_k
 #undef FLAG_f
 #undef FLAG_d
 #undef FLAG_c
 #endif
 
-// gzip ncdfk123456789[-123456789] ncdfk123456789[-123456789]
+// gzip n(no-name)cdfkt123456789[-123456789] n(no-name)cdfkt123456789[-123456789]
 #undef OPTSTR_gzip
-#define OPTSTR_gzip "ncdfk123456789[-123456789]"
+#define OPTSTR_gzip "n(no-name)cdfkt123456789[-123456789]"
 #ifdef CLEANUP_gzip
 #undef CLEANUP_gzip
 #undef FOR_gzip
@@ -1289,6 +1324,7 @@
 #undef FLAG_3
 #undef FLAG_2
 #undef FLAG_1
+#undef FLAG_t
 #undef FLAG_k
 #undef FLAG_f
 #undef FLAG_d
@@ -1385,6 +1421,15 @@
 #undef FLAG_b
 #endif
 
+// httpd   >1v
+#undef OPTSTR_httpd
+#define OPTSTR_httpd ">1v"
+#ifdef CLEANUP_httpd
+#undef CLEANUP_httpd
+#undef FOR_httpd
+#undef FLAG_v
+#endif
+
 // hwclock   >0(fast)f(rtc):u(utc)l(localtime)t(systz)s(hctosys)r(show)w(systohc)[-ul][!rtsw]
 #undef OPTSTR_hwclock
 #define OPTSTR_hwclock ">0(fast)f(rtc):u(utc)l(localtime)t(systz)s(hctosys)r(show)w(systohc)[-ul][!rtsw]"
@@ -1425,9 +1470,9 @@
 #undef FLAG_f
 #endif
 
-// i2cget   <3>3fy
+// i2cget   <2>3fy
 #undef OPTSTR_i2cget
-#define OPTSTR_i2cget "<3>3fy"
+#define OPTSTR_i2cget "<2>3fy"
 #ifdef CLEANUP_i2cget
 #undef CLEANUP_i2cget
 #undef FOR_i2cget
@@ -1505,9 +1550,9 @@
 #undef FOR_insmod
 #endif
 
-// install <1cdDpsvt:m:o:g: <1cdDpsvt:m:o:g:
+// install <1cdDp(preserve-timestamps)svt:m:o:g: <1cdDp(preserve-timestamps)svt:m:o:g:
 #undef OPTSTR_install
-#define OPTSTR_install "<1cdDpsvt:m:o:g:"
+#define OPTSTR_install "<1cdDp(preserve-timestamps)svt:m:o:g:"
 #ifdef CLEANUP_install
 #undef CLEANUP_install
 #undef FOR_install
@@ -1779,9 +1824,9 @@
 #undef FLAG_S
 #endif
 
-// ls (color):;(full-time)(show-control-chars)ZgoACFHLRSabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][!qb] (color):;(full-time)(show-control-chars)ZgoACFHLRSabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][!qb]
+// ls (sort):(color):;(full-time)(show-control-chars)¡(group-directories-first)þZgoACFHLNRSUXabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][-Nqb] (sort):(color):;(full-time)(show-control-chars)¡(group-directories-first)þZgoACFHLNRSUXabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][-Nqb]
 #undef OPTSTR_ls
-#define OPTSTR_ls "(color):;(full-time)(show-control-chars)ZgoACFHLRSabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][!qb]"
+#define OPTSTR_ls "(sort):(color):;(full-time)(show-control-chars)¡(group-directories-first)þZgoACFHLNRSUXabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][-Nqb]"
 #ifdef CLEANUP_ls
 #undef CLEANUP_ls
 #undef FOR_ls
@@ -1805,8 +1850,11 @@
 #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
@@ -1815,9 +1863,12 @@
 #undef FLAG_o
 #undef FLAG_g
 #undef FLAG_Z
+#undef FLAG_X7E
+#undef FLAG_X21
 #undef FLAG_show_control_chars
 #undef FLAG_full_time
 #undef FLAG_color
+#undef FLAG_sort
 #endif
 
 // lsattr   ldapvR
@@ -1853,13 +1904,14 @@
 #undef FLAG_l
 #endif
 
-// lspci   emkn@i:
+// lspci   emkn@x@i:
 #undef OPTSTR_lspci
-#define OPTSTR_lspci "emkn@i:"
+#define OPTSTR_lspci "emkn@x@i:"
 #ifdef CLEANUP_lspci
 #undef CLEANUP_lspci
 #undef FOR_lspci
 #undef FLAG_i
+#undef FLAG_x
 #undef FLAG_n
 #undef FLAG_k
 #undef FLAG_m
@@ -2065,9 +2117,9 @@
 #undef FOR_more
 #endif
 
-// mount   ?O:afnrvwt:o*[-rw]
+// mount   ?RO:afnrvwt:o*[-rw]
 #undef OPTSTR_mount
-#define OPTSTR_mount "?O:afnrvwt:o*[-rw]"
+#define OPTSTR_mount "?RO:afnrvwt:o*[-rw]"
 #ifdef CLEANUP_mount
 #undef CLEANUP_mount
 #undef FOR_mount
@@ -2080,6 +2132,7 @@
 #undef FLAG_f
 #undef FLAG_a
 #undef FLAG_O
+#undef FLAG_R
 #endif
 
 // mountpoint   <1qdx[-dx]
@@ -2093,9 +2146,9 @@
 #undef FLAG_q
 #endif
 
-// mv <1vnF(remove-destination)fit:T[-ni] <1vnF(remove-destination)fit:T[-ni]
+// mv <1v(verbose)nF(remove-destination)fit:T[-ni] <1v(verbose)nF(remove-destination)fit:T[-ni]
 #undef OPTSTR_mv
-#define OPTSTR_mv "<1vnF(remove-destination)fit:T[-ni]"
+#define OPTSTR_mv "<1v(verbose)nF(remove-destination)fit:T[-ni]"
 #ifdef CLEANUP_mv
 #undef CLEANUP_mv
 #undef FOR_mv
@@ -2108,22 +2161,33 @@
 #undef FLAG_v
 #endif
 
-// nbd_client   <3>3ns
+// nbd_client   <3>3b#<1>4294967295=4096ns
 #undef OPTSTR_nbd_client
-#define OPTSTR_nbd_client "<3>3ns"
+#define OPTSTR_nbd_client "<3>3b#<1>4294967295=4096ns"
 #ifdef CLEANUP_nbd_client
 #undef CLEANUP_nbd_client
 #undef FOR_nbd_client
 #undef FLAG_s
 #undef FLAG_n
+#undef FLAG_b
 #endif
 
-// netcat   ^tElLw#<1W#<1p#<1>65535q#<1s:f:46uU[!tlL][!Lw][!46U]
+// nbd_server   <1>1r
+#undef OPTSTR_nbd_server
+#define OPTSTR_nbd_server "<1>1r"
+#ifdef CLEANUP_nbd_server
+#undef CLEANUP_nbd_server
+#undef FOR_nbd_server
+#undef FLAG_r
+#endif
+
+// netcat   ^tElLw#<1W#<1p#<1>65535q#<1s:f:46uUn[!tlL][!Lw][!Lu][!46U]
 #undef OPTSTR_netcat
-#define OPTSTR_netcat "^tElLw#<1W#<1p#<1>65535q#<1s:f:46uU[!tlL][!Lw][!46U]"
+#define OPTSTR_netcat "^tElLw#<1W#<1p#<1>65535q#<1s:f:46uUn[!tlL][!Lw][!Lu][!46U]"
 #ifdef CLEANUP_netcat
 #undef CLEANUP_netcat
 #undef FOR_netcat
+#undef FLAG_n
 #undef FLAG_U
 #undef FLAG_u
 #undef FLAG_6
@@ -2200,9 +2264,9 @@
 #undef FLAG_all
 #endif
 
-// nsenter   <1F(no-fork)t#<1(target)i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user);
+// nsenter   <1a(all)F(no-fork)t#<1(target)C(cgroup):; i(ipc):; m(mount):; n(net):; p(pid):; u(uts):; U(user):; 
 #undef OPTSTR_nsenter
-#define OPTSTR_nsenter "<1F(no-fork)t#<1(target)i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user);"
+#define OPTSTR_nsenter "<1a(all)F(no-fork)t#<1(target)C(cgroup):; i(ipc):; m(mount):; n(net):; p(pid):; u(uts):; U(user):; "
 #ifdef CLEANUP_nsenter
 #undef CLEANUP_nsenter
 #undef FOR_nsenter
@@ -2212,8 +2276,10 @@
 #undef FLAG_n
 #undef FLAG_m
 #undef FLAG_i
+#undef FLAG_C
 #undef FLAG_t
 #undef FLAG_F
+#undef FLAG_a
 #endif
 
 // od j#vw#<1=16N#xsodcbA:t* j#vw#<1=16N#xsodcbA:t*
@@ -2521,17 +2587,36 @@
 #undef FLAG_dyn_syms
 #endif
 
-// readlink <1nqmef(canonicalize)[-mef] <1nqmef(canonicalize)[-mef]
+// readlink <1vnf(canonicalize)emqz[-mef][-qv] <1vnf(canonicalize)emqz[-mef][-qv]
 #undef OPTSTR_readlink
-#define OPTSTR_readlink "<1nqmef(canonicalize)[-mef]"
+#define OPTSTR_readlink "<1vnf(canonicalize)emqz[-mef][-qv]"
 #ifdef CLEANUP_readlink
 #undef CLEANUP_readlink
 #undef FOR_readlink
-#undef FLAG_f
-#undef FLAG_e
-#undef FLAG_m
+#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] <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
 
 // reboot   d:fn
@@ -2595,9 +2680,9 @@
 #undef FOR_rfkill
 #endif
 
-// rm fiRrv[-fi] fiRrv[-fi]
+// rm f(force)iRrv[-fi] f(force)iRrv[-fi]
 #undef OPTSTR_rm
-#define OPTSTR_rm "fiRrv[-fi]"
+#define OPTSTR_rm "f(force)iRrv[-fi]"
 #ifdef CLEANUP_rm
 #undef CLEANUP_rm
 #undef FOR_rm
@@ -2657,17 +2742,17 @@
 #undef FLAG_list_modes
 #endif
 
-// runcon   <2
+// runcon   ^<2
 #undef OPTSTR_runcon
-#define OPTSTR_runcon "<2"
+#define OPTSTR_runcon "^<2"
 #ifdef CLEANUP_runcon
 #undef CLEANUP_runcon
 #undef FOR_runcon
 #endif
 
-// sed (help)(version)e*f*i:;nErz(null-data)s[+Er] (help)(version)e*f*i:;nErz(null-data)s[+Er]
+// 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)e*f*i:;nErz(null-data)s[+Er]"
+#define OPTSTR_sed "(help)(version)(tarxform)e*f*i:;nErz(null-data)s[+Er]"
 #ifdef CLEANUP_sed
 #undef CLEANUP_sed
 #undef FOR_sed
@@ -2679,6 +2764,7 @@
 #undef FLAG_i
 #undef FLAG_f
 #undef FLAG_e
+#undef FLAG_tarxform
 #undef FLAG_version
 #undef FLAG_help
 #endif
@@ -2789,9 +2875,20 @@
 #undef FLAG_z
 #endif
 
-// skeleton   (walrus)(blubber):;(also):e@d*c#b:a
+// shuf   zen#<0
+#undef OPTSTR_shuf
+#define OPTSTR_shuf "zen#<0"
+#ifdef CLEANUP_shuf
+#undef CLEANUP_shuf
+#undef FOR_shuf
+#undef FLAG_n
+#undef FLAG_e
+#undef FLAG_z
+#endif
+
+// skeleton   (walrus)(blubber):;(also):h(hlong):; g(glong): f(longf):;e@d*c#b:a
 #undef OPTSTR_skeleton
-#define OPTSTR_skeleton "(walrus)(blubber):;(also):e@d*c#b:a"
+#define OPTSTR_skeleton "(walrus)(blubber):;(also):h(hlong):; g(glong): f(longf):;e@d*c#b:a"
 #ifdef CLEANUP_skeleton
 #undef CLEANUP_skeleton
 #undef FOR_skeleton
@@ -2800,6 +2897,9 @@
 #undef FLAG_c
 #undef FLAG_d
 #undef FLAG_e
+#undef FLAG_f
+#undef FLAG_g
+#undef FLAG_h
 #undef FLAG_also
 #undef FLAG_blubber
 #undef FLAG_walrus
@@ -2843,9 +2943,9 @@
 #undef FLAG_M
 #endif
 
-// sort gS:T:mo:k*t:xVbMcszdfirun gS:T:mo:k*t:xVbMcszdfirun
+// sort gS:T:mo:k*t:xVbMCcszdfirun gS:T:mo:k*t:xVbMCcszdfirun
 #undef OPTSTR_sort
-#define OPTSTR_sort "gS:T:mo:k*t:xVbMcszdfirun"
+#define OPTSTR_sort "gS:T:mo:k*t:xVbMCcszdfirun"
 #ifdef CLEANUP_sort
 #undef CLEANUP_sort
 #undef FOR_sort
@@ -2858,6 +2958,7 @@
 #undef FLAG_z
 #undef FLAG_s
 #undef FLAG_c
+#undef FLAG_C
 #undef FLAG_M
 #undef FLAG_b
 #undef FLAG_V
@@ -2962,12 +3063,14 @@
 #undef FLAG_t
 #endif
 
-// swapoff   <1>1
+// swapoff   <1>1av
 #undef OPTSTR_swapoff
-#define OPTSTR_swapoff "<1>1"
+#define OPTSTR_swapoff "<1>1av"
 #ifdef CLEANUP_swapoff
 #undef CLEANUP_swapoff
 #undef FOR_swapoff
+#undef FLAG_v
+#undef FLAG_a
 #endif
 
 // swapon   <1>1p#<0>32767d
@@ -3057,15 +3160,17 @@
 #undef FLAG_f
 #endif
 
-// tar &(strip-components)#(selinux)(restrict)(full-time)(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mode):(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)I(use-compress-program):J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):a[!txc][!jzJa] &(strip-components)#(selinux)(restrict)(full-time)(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mode):(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)I(use-compress-program):J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):a[!txc][!jzJa]
+// tar &(no-ignore-case)(ignore-case)(no-anchored)(anchored)(no-wildcards)(wildcards)(no-wildcards-match-slash)(wildcards-match-slash)(show-transformed-names)(selinux)(restrict)(full-time)(no-recursion)(null)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(sort);:(mode):(mtime):(group):(owner):(to-command):~(strip-components)(strip)#~(transform)(xform)*o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*I(use-compress-program):C(directory):f(file):as[!txc][!jzJa] &(no-ignore-case)(ignore-case)(no-anchored)(anchored)(no-wildcards)(wildcards)(no-wildcards-match-slash)(wildcards-match-slash)(show-transformed-names)(selinux)(restrict)(full-time)(no-recursion)(null)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(sort);:(mode):(mtime):(group):(owner):(to-command):~(strip-components)(strip)#~(transform)(xform)*o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*I(use-compress-program):C(directory):f(file):as[!txc][!jzJa]
 #undef OPTSTR_tar
-#define OPTSTR_tar "&(strip-components)#(selinux)(restrict)(full-time)(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mode):(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)I(use-compress-program):J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):a[!txc][!jzJa]"
+#define OPTSTR_tar "&(no-ignore-case)(ignore-case)(no-anchored)(anchored)(no-wildcards)(wildcards)(no-wildcards-match-slash)(wildcards-match-slash)(show-transformed-names)(selinux)(restrict)(full-time)(no-recursion)(null)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(sort);:(mode):(mtime):(group):(owner):(to-command):~(strip-components)(strip)#~(transform)(xform)*o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*I(use-compress-program):C(directory):f(file):as[!txc][!jzJa]"
 #ifdef CLEANUP_tar
 #undef CLEANUP_tar
 #undef FOR_tar
+#undef FLAG_s
 #undef FLAG_a
 #undef FLAG_f
 #undef FLAG_C
+#undef FLAG_I
 #undef FLAG_T
 #undef FLAG_X
 #undef FLAG_m
@@ -3075,7 +3180,6 @@
 #undef FLAG_z
 #undef FLAG_j
 #undef FLAG_J
-#undef FLAG_I
 #undef FLAG_v
 #undef FLAG_t
 #undef FLAG_x
@@ -3084,20 +3188,32 @@
 #undef FLAG_k
 #undef FLAG_p
 #undef FLAG_o
+#undef FLAG_xform
+#undef FLAG_strip
 #undef FLAG_to_command
 #undef FLAG_owner
 #undef FLAG_group
 #undef FLAG_mtime
 #undef FLAG_mode
+#undef FLAG_sort
 #undef FLAG_exclude
 #undef FLAG_overwrite
 #undef FLAG_no_same_permissions
 #undef FLAG_numeric_owner
+#undef FLAG_null
 #undef FLAG_no_recursion
 #undef FLAG_full_time
 #undef FLAG_restrict
 #undef FLAG_selinux
-#undef FLAG_strip_components
+#undef FLAG_show_transformed_names
+#undef FLAG_wildcards_match_slash
+#undef FLAG_no_wildcards_match_slash
+#undef FLAG_wildcards
+#undef FLAG_no_wildcards
+#undef FLAG_anchored
+#undef FLAG_no_anchored
+#undef FLAG_ignore_case
+#undef FLAG_no_ignore_case
 #endif
 
 // taskset   <1^pa
@@ -3110,9 +3226,9 @@
 #undef FLAG_p
 #endif
 
-// tcpsvd   ^<3c#=30<1C:b#=20<0u:l:hEv
+// tcpsvd   ^<3c#=30<1b#=20<0C:u:l:hEv
 #undef OPTSTR_tcpsvd
-#define OPTSTR_tcpsvd "^<3c#=30<1C:b#=20<0u:l:hEv"
+#define OPTSTR_tcpsvd "^<3c#=30<1b#=20<0C:u:l:hEv"
 #ifdef CLEANUP_tcpsvd
 #undef CLEANUP_tcpsvd
 #undef FOR_tcpsvd
@@ -3121,8 +3237,8 @@
 #undef FLAG_h
 #undef FLAG_l
 #undef FLAG_u
-#undef FLAG_b
 #undef FLAG_C
+#undef FLAG_b
 #undef FLAG_c
 #endif
 
@@ -3204,12 +3320,13 @@
 #undef FLAG_p
 #endif
 
-// timeout <2^(foreground)(preserve-status)vk:s(signal): <2^(foreground)(preserve-status)vk:s(signal):
+// timeout <2^(foreground)(preserve-status)vk:s(signal):i <2^(foreground)(preserve-status)vk:s(signal):i
 #undef OPTSTR_timeout
-#define OPTSTR_timeout "<2^(foreground)(preserve-status)vk:s(signal):"
+#define OPTSTR_timeout "<2^(foreground)(preserve-status)vk:s(signal):i"
 #ifdef CLEANUP_timeout
 #undef CLEANUP_timeout
 #undef FOR_timeout
+#undef FLAG_i
 #undef FLAG_s
 #undef FLAG_k
 #undef FLAG_v
@@ -3400,9 +3517,9 @@
 #undef FLAG_c
 #endif
 
-// uname aomvrns aomvrns
+// uname paomvrns paomvrns
 #undef OPTSTR_uname
-#define OPTSTR_uname "aomvrns"
+#define OPTSTR_uname "paomvrns"
 #ifdef CLEANUP_uname
 #undef CLEANUP_uname
 #undef FOR_uname
@@ -3413,6 +3530,7 @@
 #undef FLAG_m
 #undef FLAG_o
 #undef FLAG_a
+#undef FLAG_p
 #endif
 
 // unicode   <1
@@ -3466,9 +3584,9 @@
 #undef FLAG_f
 #endif
 
-// unshare   <1^f(fork);r(map-root-user);i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user);
+// unshare   <1^a(all)f(fork)r(map-root-user)C(cgroup):; i(ipc):; m(mount):; n(net):; p(pid):; u(uts):; U(user):; 
 #undef OPTSTR_unshare
-#define OPTSTR_unshare "<1^f(fork);r(map-root-user);i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user);"
+#define OPTSTR_unshare "<1^a(all)f(fork)r(map-root-user)C(cgroup):; i(ipc):; m(mount):; n(net):; p(pid):; u(uts):; U(user):; "
 #ifdef CLEANUP_unshare
 #undef CLEANUP_unshare
 #undef FOR_unshare
@@ -3478,8 +3596,10 @@
 #undef FLAG_n
 #undef FLAG_m
 #undef FLAG_i
+#undef FLAG_C
 #undef FLAG_r
 #undef FLAG_f
+#undef FLAG_a
 #endif
 
 // uptime   >0ps
@@ -3517,9 +3637,9 @@
 #undef FLAG_r
 #endif
 
-// usleep   <1
+// usleep   <1>1
 #undef OPTSTR_usleep
-#define OPTSTR_usleep "<1"
+#define OPTSTR_usleep "<1>1"
 #ifdef CLEANUP_usleep
 #undef CLEANUP_usleep
 #undef FOR_usleep
@@ -3661,9 +3781,9 @@
 #undef FLAG_a
 #endif
 
-// xargs ^E:P#<0=1optrn#<1(max-args)s#0[!0E] ^E:P#<0=1optrn#<1(max-args)s#0[!0E]
+// 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=1optrn#<1(max-args)s#0[!0E]"
+#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
@@ -3678,9 +3798,9 @@
 #undef FLAG_E
 #endif
 
-// xxd >1c#<0>256l#o#g#<1=2iprs#[!rs] >1c#<0>256l#o#g#<1=2iprs#[!rs]
+// xxd >1c#<0>256l#o#g#<0=2eiprs#[!rs][!re] >1c#<0>256l#o#g#<0=2eiprs#[!rs][!re]
 #undef OPTSTR_xxd
-#define OPTSTR_xxd ">1c#<0>256l#o#g#<1=2iprs#[!rs]"
+#define OPTSTR_xxd ">1c#<0>256l#o#g#<0=2eiprs#[!rs][!re]"
 #ifdef CLEANUP_xxd
 #undef CLEANUP_xxd
 #undef FOR_xxd
@@ -3688,6 +3808,7 @@
 #undef FLAG_r
 #undef FLAG_p
 #undef FLAG_i
+#undef FLAG_e
 #undef FLAG_g
 #undef FLAG_o
 #undef FLAG_l
@@ -3710,9 +3831,9 @@
 #undef FOR_yes
 #endif
 
-// zcat cdfk123456789[-123456789] cdfk123456789[-123456789]
+// zcat cdfkt123456789[-123456789] cdfkt123456789[-123456789]
 #undef OPTSTR_zcat
-#define OPTSTR_zcat "cdfk123456789[-123456789]"
+#define OPTSTR_zcat "cdfkt123456789[-123456789]"
 #ifdef CLEANUP_zcat
 #undef CLEANUP_zcat
 #undef FOR_zcat
@@ -3725,6 +3846,7 @@
 #undef FLAG_3
 #undef FLAG_2
 #undef FLAG_1
+#undef FLAG_t
 #undef FLAG_k
 #undef FLAG_f
 #undef FLAG_d
@@ -3816,8 +3938,8 @@
 #ifndef TT
 #define TT this.basename
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_a (1<<1)
+#define FLAG_s (1LL<<0)
+#define FLAG_a (1LL<<1)
 #endif
 
 #ifdef FOR_bc
@@ -3850,8 +3972,9 @@
 #define TT this.blkid
 #endif
 #define FLAG_s (FORCED_FLAG<<0)
-#define FLAG_L (FORCED_FLAG<<1)
-#define FLAG_U (FORCED_FLAG<<2)
+#define FLAG_o (FORCED_FLAG<<1)
+#define FLAG_L (FORCED_FLAG<<2)
+#define FLAG_U (FORCED_FLAG<<3)
 #endif
 
 #ifdef FOR_blockdev
@@ -3920,20 +4043,10 @@
 #ifndef TT
 #define TT this.cat
 #endif
-#define FLAG_e (1<<0)
-#define FLAG_t (1<<1)
-#define FLAG_v (1<<2)
-#define FLAG_u (1<<3)
-#endif
-
-#ifdef FOR_catv
-#define CLEANUP_catv
-#ifndef TT
-#define TT this.catv
-#endif
-#define FLAG_e (FORCED_FLAG<<0)
-#define FLAG_t (FORCED_FLAG<<1)
-#define FLAG_v (FORCED_FLAG<<2)
+#define FLAG_e (1LL<<0)
+#define FLAG_t (1LL<<1)
+#define FLAG_v (1LL<<2)
+#define FLAG_u (1LL<<3)
 #endif
 
 #ifdef FOR_cd
@@ -3984,9 +4097,9 @@
 #ifndef TT
 #define TT this.chmod
 #endif
-#define FLAG_R (1<<0)
-#define FLAG_f (1<<1)
-#define FLAG_v (1<<2)
+#define FLAG_R (1LL<<0)
+#define FLAG_f (1LL<<1)
+#define FLAG_v (1LL<<2)
 #endif
 
 #ifdef FOR_chroot
@@ -4050,9 +4163,9 @@
 #ifndef TT
 #define TT this.cmp
 #endif
-#define FLAG_n (1<<0)
-#define FLAG_s (1<<1)
-#define FLAG_l (1<<2)
+#define FLAG_n (1LL<<0)
+#define FLAG_s (1LL<<1)
+#define FLAG_l (1LL<<2)
 #endif
 
 #ifdef FOR_comm
@@ -4060,9 +4173,9 @@
 #ifndef TT
 #define TT this.comm
 #endif
-#define FLAG_1 (1<<0)
-#define FLAG_2 (1<<1)
-#define FLAG_3 (1<<2)
+#define FLAG_1 (1LL<<0)
+#define FLAG_2 (1LL<<1)
+#define FLAG_3 (1LL<<2)
 #endif
 
 #ifdef FOR_count
@@ -4077,26 +4190,26 @@
 #ifndef TT
 #define TT this.cp
 #endif
-#define FLAG_T (1<<0)
-#define FLAG_t (1<<1)
-#define FLAG_i (1<<2)
-#define FLAG_f (1<<3)
-#define FLAG_F (1<<4)
-#define FLAG_n (1<<5)
-#define FLAG_v (1<<6)
-#define FLAG_l (1<<7)
-#define FLAG_s (1<<8)
-#define FLAG_a (1<<9)
-#define FLAG_d (1<<10)
-#define FLAG_u (1<<11)
-#define FLAG_r (1<<12)
-#define FLAG_p (1<<13)
-#define FLAG_P (1<<14)
-#define FLAG_L (1<<15)
-#define FLAG_H (1<<16)
-#define FLAG_R (1<<17)
-#define FLAG_D (1<<18)
-#define FLAG_preserve (1<<19)
+#define FLAG_T (1LL<<0)
+#define FLAG_t (1LL<<1)
+#define FLAG_i (1LL<<2)
+#define FLAG_f (1LL<<3)
+#define FLAG_F (1LL<<4)
+#define FLAG_n (1LL<<5)
+#define FLAG_v (1LL<<6)
+#define FLAG_l (1LL<<7)
+#define FLAG_s (1LL<<8)
+#define FLAG_a (1LL<<9)
+#define FLAG_d (1LL<<10)
+#define FLAG_u (1LL<<11)
+#define FLAG_r (1LL<<12)
+#define FLAG_p (1LL<<13)
+#define FLAG_P (1LL<<14)
+#define FLAG_L (1LL<<15)
+#define FLAG_H (1LL<<16)
+#define FLAG_R (1LL<<17)
+#define FLAG_D (1LL<<18)
+#define FLAG_preserve (1LL<<19)
 #endif
 
 #ifdef FOR_cpio
@@ -4104,20 +4217,21 @@
 #ifndef TT
 #define TT this.cpio
 #endif
-#define FLAG_o (1<<0)
-#define FLAG_v (1<<1)
-#define FLAG_F (1<<2)
-#define FLAG_t (1<<3)
-#define FLAG_i (1<<4)
-#define FLAG_p (1<<5)
-#define FLAG_H (1<<6)
-#define FLAG_u (1<<7)
-#define FLAG_d (1<<8)
-#define FLAG_m (1<<9)
-#define FLAG_no_preserve_owner (1<<10)
-#define FLAG_quiet (1<<11)
-#define FLAG_renumber_inodes (1<<12)
-#define FLAG_ignore_devno (1<<13)
+#define FLAG_o (1LL<<0)
+#define FLAG_v (1LL<<1)
+#define FLAG_F (1LL<<2)
+#define FLAG_t (1LL<<3)
+#define FLAG_i (1LL<<4)
+#define FLAG_p (1LL<<5)
+#define FLAG_H (1LL<<6)
+#define FLAG_u (1LL<<7)
+#define FLAG_d (1LL<<8)
+#define FLAG_m (1LL<<9)
+#define FLAG_R (1LL<<10)
+#define FLAG_no_preserve_owner (1LL<<11)
+#define FLAG_quiet (1LL<<12)
+#define FLAG_renumber_inodes (1LL<<13)
+#define FLAG_ignore_devno (1LL<<14)
 #endif
 
 #ifdef FOR_crc32
@@ -4158,16 +4272,16 @@
 #ifndef TT
 #define TT this.cut
 #endif
-#define FLAG_n (1<<0)
-#define FLAG_D (1<<1)
-#define FLAG_s (1<<2)
-#define FLAG_d (1<<3)
-#define FLAG_O (1<<4)
-#define FLAG_C (1<<5)
-#define FLAG_F (1<<6)
-#define FLAG_f (1<<7)
-#define FLAG_c (1<<8)
-#define FLAG_b (1<<9)
+#define FLAG_n (1LL<<0)
+#define FLAG_D (1LL<<1)
+#define FLAG_s (1LL<<2)
+#define FLAG_d (1LL<<3)
+#define FLAG_O (1LL<<4)
+#define FLAG_C (1LL<<5)
+#define FLAG_F (1LL<<6)
+#define FLAG_f (1LL<<7)
+#define FLAG_c (1LL<<8)
+#define FLAG_b (1LL<<9)
 #endif
 
 #ifdef FOR_date
@@ -4175,12 +4289,12 @@
 #ifndef TT
 #define TT this.date
 #endif
-#define FLAG_u (1<<0)
-#define FLAG_s (1<<1)
-#define FLAG_r (1<<2)
-#define FLAG_I (1<<3)
-#define FLAG_D (1<<4)
-#define FLAG_d (1<<5)
+#define FLAG_u (1LL<<0)
+#define FLAG_s (1LL<<1)
+#define FLAG_r (1LL<<2)
+#define FLAG_I (1LL<<3)
+#define FLAG_D (1LL<<4)
+#define FLAG_d (1LL<<5)
 #endif
 
 #ifdef FOR_dd
@@ -4249,27 +4363,27 @@
 #define FLAG_C (FORCED_FLAG<<28)
 #define FLAG_D (FORCED_FLAG<<29)
 #define FLAG_E (FORCED_FLAG<<30)
-#define FLAG_F (FORCED_FLAGLL<<31)
-#define FLAG_G (FORCED_FLAGLL<<32)
-#define FLAG_H (FORCED_FLAGLL<<33)
-#define FLAG_I (FORCED_FLAGLL<<34)
-#define FLAG_J (FORCED_FLAGLL<<35)
-#define FLAG_K (FORCED_FLAGLL<<36)
-#define FLAG_L (FORCED_FLAGLL<<37)
-#define FLAG_M (FORCED_FLAGLL<<38)
-#define FLAG_N (FORCED_FLAGLL<<39)
-#define FLAG_O (FORCED_FLAGLL<<40)
-#define FLAG_P (FORCED_FLAGLL<<41)
-#define FLAG_Q (FORCED_FLAGLL<<42)
-#define FLAG_R (FORCED_FLAGLL<<43)
-#define FLAG_S (FORCED_FLAGLL<<44)
-#define FLAG_T (FORCED_FLAGLL<<45)
-#define FLAG_U (FORCED_FLAGLL<<46)
-#define FLAG_V (FORCED_FLAGLL<<47)
-#define FLAG_W (FORCED_FLAGLL<<48)
-#define FLAG_X (FORCED_FLAGLL<<49)
-#define FLAG_Y (FORCED_FLAGLL<<50)
-#define FLAG_Z (FORCED_FLAGLL<<51)
+#define FLAG_F (FORCED_FLAG<<31)
+#define FLAG_G (FORCED_FLAG<<32)
+#define FLAG_H (FORCED_FLAG<<33)
+#define FLAG_I (FORCED_FLAG<<34)
+#define FLAG_J (FORCED_FLAG<<35)
+#define FLAG_K (FORCED_FLAG<<36)
+#define FLAG_L (FORCED_FLAG<<37)
+#define FLAG_M (FORCED_FLAG<<38)
+#define FLAG_N (FORCED_FLAG<<39)
+#define FLAG_O (FORCED_FLAG<<40)
+#define FLAG_P (FORCED_FLAG<<41)
+#define FLAG_Q (FORCED_FLAG<<42)
+#define FLAG_R (FORCED_FLAG<<43)
+#define FLAG_S (FORCED_FLAG<<44)
+#define FLAG_T (FORCED_FLAG<<45)
+#define FLAG_U (FORCED_FLAG<<46)
+#define FLAG_V (FORCED_FLAG<<47)
+#define FLAG_W (FORCED_FLAG<<48)
+#define FLAG_X (FORCED_FLAG<<49)
+#define FLAG_Y (FORCED_FLAG<<50)
+#define FLAG_Z (FORCED_FLAG<<51)
 #endif
 
 #ifdef FOR_demo_number
@@ -4390,24 +4504,28 @@
 #ifndef TT
 #define TT this.diff
 #endif
-#define FLAG_U (1<<0)
-#define FLAG_r (1<<1)
-#define FLAG_N (1<<2)
-#define FLAG_S (1<<3)
-#define FLAG_L (1<<4)
-#define FLAG_a (1<<5)
-#define FLAG_q (1<<6)
-#define FLAG_s (1<<7)
-#define FLAG_T (1<<8)
-#define FLAG_i (1<<9)
-#define FLAG_w (1<<10)
-#define FLAG_t (1<<11)
-#define FLAG_u (1<<12)
-#define FLAG_b (1<<13)
-#define FLAG_d (1<<14)
-#define FLAG_B (1<<15)
-#define FLAG_strip_trailing_cr (1<<16)
-#define FLAG_color (1<<17)
+#define FLAG_U (1LL<<0)
+#define FLAG_r (1LL<<1)
+#define FLAG_N (1LL<<2)
+#define FLAG_L (1LL<<3)
+#define FLAG_F (1LL<<4)
+#define FLAG_S (1LL<<5)
+#define FLAG_a (1LL<<6)
+#define FLAG_q (1LL<<7)
+#define FLAG_s (1LL<<8)
+#define FLAG_T (1LL<<9)
+#define FLAG_i (1LL<<10)
+#define FLAG_w (1LL<<11)
+#define FLAG_t (1LL<<12)
+#define FLAG_u (1LL<<13)
+#define FLAG_b (1LL<<14)
+#define FLAG_d (1LL<<15)
+#define FLAG_B (1LL<<16)
+#define FLAG_strip_trailing_cr (1LL<<17)
+#define FLAG_color (1LL<<18)
+#define FLAG_new_line_format (1LL<<19)
+#define FLAG_old_line_format (1LL<<20)
+#define FLAG_unchanged_line_format (1LL<<21)
 #endif
 
 #ifdef FOR_dirname
@@ -4452,19 +4570,19 @@
 #ifndef TT
 #define TT this.du
 #endif
-#define FLAG_b (1<<0)
-#define FLAG_x (1<<1)
-#define FLAG_s (1<<2)
-#define FLAG_L (1<<3)
-#define FLAG_K (1<<4)
-#define FLAG_k (1<<5)
-#define FLAG_H (1<<6)
-#define FLAG_a (1<<7)
-#define FLAG_c (1<<8)
-#define FLAG_l (1<<9)
-#define FLAG_m (1<<10)
-#define FLAG_h (1<<11)
-#define FLAG_d (1<<12)
+#define FLAG_b (1LL<<0)
+#define FLAG_x (1LL<<1)
+#define FLAG_s (1LL<<2)
+#define FLAG_L (1LL<<3)
+#define FLAG_K (1LL<<4)
+#define FLAG_k (1LL<<5)
+#define FLAG_H (1LL<<6)
+#define FLAG_a (1LL<<7)
+#define FLAG_c (1LL<<8)
+#define FLAG_l (1LL<<9)
+#define FLAG_m (1LL<<10)
+#define FLAG_h (1LL<<11)
+#define FLAG_d (1LL<<12)
 #endif
 
 #ifdef FOR_dumpleases
@@ -4482,9 +4600,9 @@
 #ifndef TT
 #define TT this.echo
 #endif
-#define FLAG_n (1<<0)
-#define FLAG_e (1<<1)
-#define FLAG_E (1<<2)
+#define FLAG_n (1LL<<0)
+#define FLAG_e (1LL<<1)
+#define FLAG_E (1LL<<2)
 #endif
 
 #ifdef FOR_eject
@@ -4502,9 +4620,9 @@
 #ifndef TT
 #define TT this.env
 #endif
-#define FLAG_u (1<<0)
-#define FLAG_0 (1<<1)
-#define FLAG_i (1<<2)
+#define FLAG_u (1LL<<0)
+#define FLAG_0 (1LL<<1)
+#define FLAG_i (1LL<<2)
 #endif
 
 #ifdef FOR_eval
@@ -4560,6 +4678,8 @@
 #ifndef TT
 #define TT this.factor
 #endif
+#define FLAG_x (FORCED_FLAG<<0)
+#define FLAG_h (FORCED_FLAG<<1)
 #endif
 
 #ifdef FOR_fallocate
@@ -4596,10 +4716,10 @@
 #ifndef TT
 #define TT this.file
 #endif
-#define FLAG_s (FORCED_FLAG<<0)
-#define FLAG_L (FORCED_FLAG<<1)
-#define FLAG_h (FORCED_FLAG<<2)
-#define FLAG_b (FORCED_FLAG<<3)
+#define FLAG_s (1LL<<0)
+#define FLAG_L (1LL<<1)
+#define FLAG_h (1LL<<2)
+#define FLAG_b (1LL<<3)
 #endif
 
 #ifdef FOR_find
@@ -4607,8 +4727,8 @@
 #ifndef TT
 #define TT this.find
 #endif
-#define FLAG_L (1<<0)
-#define FLAG_H (1<<1)
+#define FLAG_L (1LL<<0)
+#define FLAG_H (1LL<<1)
 #endif
 
 #ifdef FOR_flock
@@ -4725,8 +4845,8 @@
 #ifndef TT
 #define TT this.getconf
 #endif
-#define FLAG_l (1<<0)
-#define FLAG_a (1<<1)
+#define FLAG_l (1LL<<0)
+#define FLAG_a (1LL<<1)
 #endif
 
 #ifdef FOR_getenforce
@@ -4752,12 +4872,12 @@
 #ifndef TT
 #define TT this.getopt
 #endif
-#define FLAG_u (1<<0)
-#define FLAG_T (1<<1)
-#define FLAG_l (1<<2)
-#define FLAG_o (1<<3)
-#define FLAG_n (1<<4)
-#define FLAG_a (1<<5)
+#define FLAG_u (1LL<<0)
+#define FLAG_T (1LL<<1)
+#define FLAG_l (1LL<<2)
+#define FLAG_o (1LL<<3)
+#define FLAG_n (1LL<<4)
+#define FLAG_a (1LL<<5)
 #endif
 
 #ifdef FOR_getty
@@ -4778,6 +4898,41 @@
 #define FLAG_t (FORCED_FLAG<<10)
 #endif
 
+#ifdef FOR_gitcheckout
+#define CLEANUP_gitcheckout
+#ifndef TT
+#define TT this.gitcheckout
+#endif
+#endif
+
+#ifdef FOR_gitclone
+#define CLEANUP_gitclone
+#ifndef TT
+#define TT this.gitclone
+#endif
+#endif
+
+#ifdef FOR_gitfetch
+#define CLEANUP_gitfetch
+#ifndef TT
+#define TT this.gitfetch
+#endif
+#endif
+
+#ifdef FOR_gitinit
+#define CLEANUP_gitinit
+#ifndef TT
+#define TT this.gitinit
+#endif
+#endif
+
+#ifdef FOR_gitremote
+#define CLEANUP_gitremote
+#ifndef TT
+#define TT this.gitremote
+#endif
+#endif
+
 #ifdef FOR_gpiodetect
 #define CLEANUP_gpiodetect
 #ifndef TT
@@ -4820,37 +4975,37 @@
 #ifndef TT
 #define TT this.grep
 #endif
-#define FLAG_x (1<<0)
-#define FLAG_m (1<<1)
-#define FLAG_A (1<<2)
-#define FLAG_B (1<<3)
-#define FLAG_C (1<<4)
-#define FLAG_f (1<<5)
-#define FLAG_e (1<<6)
-#define FLAG_q (1<<7)
-#define FLAG_l (1<<8)
-#define FLAG_L (1<<9)
-#define FLAG_c (1<<10)
-#define FLAG_w (1<<11)
-#define FLAG_v (1<<12)
-#define FLAG_s (1<<13)
-#define FLAG_R (1<<14)
-#define FLAG_r (1<<15)
-#define FLAG_o (1<<16)
-#define FLAG_n (1<<17)
-#define FLAG_i (1<<18)
-#define FLAG_h (1<<19)
-#define FLAG_b (1<<20)
-#define FLAG_a (1<<21)
-#define FLAG_I (1<<22)
-#define FLAG_H (1<<23)
-#define FLAG_F (1<<24)
-#define FLAG_E (1<<25)
-#define FLAG_z (1<<26)
-#define FLAG_Z (1<<27)
-#define FLAG_M (1<<28)
-#define FLAG_S (1<<29)
-#define FLAG_exclude_dir (1<<30)
+#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
@@ -4892,10 +5047,11 @@
 #define FLAG_3 (FORCED_FLAG<<6)
 #define FLAG_2 (FORCED_FLAG<<7)
 #define FLAG_1 (FORCED_FLAG<<8)
-#define FLAG_k (FORCED_FLAG<<9)
-#define FLAG_f (FORCED_FLAG<<10)
-#define FLAG_d (FORCED_FLAG<<11)
-#define FLAG_c (FORCED_FLAG<<12)
+#define FLAG_t (FORCED_FLAG<<9)
+#define FLAG_k (FORCED_FLAG<<10)
+#define FLAG_f (FORCED_FLAG<<11)
+#define FLAG_d (FORCED_FLAG<<12)
+#define FLAG_c (FORCED_FLAG<<13)
 #endif
 
 #ifdef FOR_gzip
@@ -4903,20 +5059,21 @@
 #ifndef TT
 #define TT this.gzip
 #endif
-#define FLAG_9 (1<<0)
-#define FLAG_8 (1<<1)
-#define FLAG_7 (1<<2)
-#define FLAG_6 (1<<3)
-#define FLAG_5 (1<<4)
-#define FLAG_4 (1<<5)
-#define FLAG_3 (1<<6)
-#define FLAG_2 (1<<7)
-#define FLAG_1 (1<<8)
-#define FLAG_k (1<<9)
-#define FLAG_f (1<<10)
-#define FLAG_d (1<<11)
-#define FLAG_c (1<<12)
-#define FLAG_n (1<<13)
+#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
@@ -4924,10 +5081,10 @@
 #ifndef TT
 #define TT this.head
 #endif
-#define FLAG_v (1<<0)
-#define FLAG_q (1<<1)
-#define FLAG_c (1<<2)
-#define FLAG_n (1<<3)
+#define FLAG_v (1LL<<0)
+#define FLAG_q (1LL<<1)
+#define FLAG_c (1LL<<2)
+#define FLAG_n (1LL<<3)
 #endif
 
 #ifdef FOR_hello
@@ -4993,11 +5150,19 @@
 #ifndef TT
 #define TT this.hostname
 #endif
-#define FLAG_F (1<<0)
-#define FLAG_f (1<<1)
-#define FLAG_s (1<<2)
-#define FLAG_d (1<<3)
-#define FLAG_b (1<<4)
+#define FLAG_F (1LL<<0)
+#define FLAG_f (1LL<<1)
+#define FLAG_s (1LL<<2)
+#define FLAG_d (1LL<<3)
+#define FLAG_b (1LL<<4)
+#endif
+
+#ifdef FOR_httpd
+#define CLEANUP_httpd
+#ifndef TT
+#define TT this.httpd
+#endif
+#define FLAG_v (FORCED_FLAG<<0)
 #endif
 
 #ifdef FOR_hwclock
@@ -5071,11 +5236,11 @@
 #ifndef TT
 #define TT this.id
 #endif
-#define FLAG_u (1<<0)
-#define FLAG_r (1<<1)
-#define FLAG_g (1<<2)
-#define FLAG_G (1<<3)
-#define FLAG_n (1<<4)
+#define FLAG_u (1LL<<0)
+#define FLAG_r (1LL<<1)
+#define FLAG_g (1LL<<2)
+#define FLAG_G (1LL<<3)
+#define FLAG_n (1LL<<4)
 #define FLAG_Z (FORCED_FLAG<<5)
 #endif
 
@@ -5114,16 +5279,16 @@
 #ifndef TT
 #define TT this.install
 #endif
-#define FLAG_g (1<<0)
-#define FLAG_o (1<<1)
-#define FLAG_m (1<<2)
-#define FLAG_t (1<<3)
-#define FLAG_v (1<<4)
-#define FLAG_s (1<<5)
-#define FLAG_p (1<<6)
-#define FLAG_D (1<<7)
-#define FLAG_d (1<<8)
-#define FLAG_c (1<<9)
+#define FLAG_g (1LL<<0)
+#define FLAG_o (1LL<<1)
+#define FLAG_m (1LL<<2)
+#define FLAG_t (1LL<<3)
+#define FLAG_v (1LL<<4)
+#define FLAG_s (1LL<<5)
+#define FLAG_p (1LL<<6)
+#define FLAG_D (1LL<<7)
+#define FLAG_d (1LL<<8)
+#define FLAG_c (1LL<<9)
 #endif
 
 #ifdef FOR_ionice
@@ -5284,13 +5449,13 @@
 #ifndef TT
 #define TT this.ln
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_f (1<<1)
-#define FLAG_n (1<<2)
-#define FLAG_v (1<<3)
-#define FLAG_T (1<<4)
-#define FLAG_t (1<<5)
-#define FLAG_r (1<<6)
+#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_load_policy
@@ -5365,39 +5530,45 @@
 #ifndef TT
 #define TT this.ls
 #endif
-#define FLAG_1 (1<<0)
-#define FLAG_x (1<<1)
-#define FLAG_w (1<<2)
-#define FLAG_u (1<<3)
-#define FLAG_t (1<<4)
-#define FLAG_s (1<<5)
-#define FLAG_r (1<<6)
-#define FLAG_q (1<<7)
-#define FLAG_p (1<<8)
-#define FLAG_n (1<<9)
-#define FLAG_m (1<<10)
-#define FLAG_l (1<<11)
-#define FLAG_k (1<<12)
-#define FLAG_i (1<<13)
-#define FLAG_h (1<<14)
-#define FLAG_f (1<<15)
-#define FLAG_d (1<<16)
-#define FLAG_c (1<<17)
-#define FLAG_b (1<<18)
-#define FLAG_a (1<<19)
-#define FLAG_S (1<<20)
-#define FLAG_R (1<<21)
-#define FLAG_L (1<<22)
-#define FLAG_H (1<<23)
-#define FLAG_F (1<<24)
-#define FLAG_C (1<<25)
-#define FLAG_A (1<<26)
-#define FLAG_o (1<<27)
-#define FLAG_g (1<<28)
-#define FLAG_Z (1<<29)
-#define FLAG_show_control_chars (1<<30)
-#define FLAG_full_time (1LL<<31)
-#define FLAG_color (1LL<<32)
+#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_show_control_chars (1LL<<35)
+#define FLAG_full_time (1LL<<36)
+#define FLAG_color (1LL<<37)
+#define FLAG_sort (1LL<<38)
 #endif
 
 #ifdef FOR_lsattr
@@ -5436,10 +5607,11 @@
 #define TT this.lspci
 #endif
 #define FLAG_i (FORCED_FLAG<<0)
-#define FLAG_n (FORCED_FLAG<<1)
-#define FLAG_k (FORCED_FLAG<<2)
-#define FLAG_m (FORCED_FLAG<<3)
-#define FLAG_e (FORCED_FLAG<<4)
+#define FLAG_x (FORCED_FLAG<<1)
+#define FLAG_n (FORCED_FLAG<<2)
+#define FLAG_k (FORCED_FLAG<<3)
+#define FLAG_m (FORCED_FLAG<<4)
+#define FLAG_e (FORCED_FLAG<<5)
 #endif
 
 #ifdef FOR_lsusb
@@ -5481,9 +5653,9 @@
 #ifndef TT
 #define TT this.md5sum
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_c (1<<1)
-#define FLAG_b (1<<2)
+#define FLAG_s (1LL<<0)
+#define FLAG_c (1LL<<1)
+#define FLAG_b (1LL<<2)
 #endif
 
 #ifdef FOR_mdev
@@ -5499,8 +5671,8 @@
 #ifndef TT
 #define TT this.microcom
 #endif
-#define FLAG_X (1<<0)
-#define FLAG_s (1<<1)
+#define FLAG_X (1LL<<0)
+#define FLAG_s (1LL<<1)
 #endif
 
 #ifdef FOR_mix
@@ -5519,9 +5691,9 @@
 #ifndef TT
 #define TT this.mkdir
 #endif
-#define FLAG_m (1<<0)
-#define FLAG_p (1<<1)
-#define FLAG_v (1<<2)
+#define FLAG_m (1LL<<0)
+#define FLAG_p (1LL<<1)
+#define FLAG_v (1LL<<2)
 #define FLAG_Z (FORCED_FLAG<<3)
 #endif
 
@@ -5581,12 +5753,12 @@
 #ifndef TT
 #define TT this.mktemp
 #endif
-#define FLAG_t (1<<0)
-#define FLAG_p (1<<1)
-#define FLAG_d (1<<2)
-#define FLAG_q (1<<3)
-#define FLAG_u (1<<4)
-#define FLAG_tmpdir (1<<5)
+#define FLAG_t (1LL<<0)
+#define FLAG_p (1LL<<1)
+#define FLAG_d (1LL<<2)
+#define FLAG_q (1LL<<3)
+#define FLAG_u (1LL<<4)
+#define FLAG_tmpdir (1LL<<5)
 #endif
 
 #ifdef FOR_modinfo
@@ -5637,6 +5809,7 @@
 #define FLAG_f (FORCED_FLAG<<6)
 #define FLAG_a (FORCED_FLAG<<7)
 #define FLAG_O (FORCED_FLAG<<8)
+#define FLAG_R (FORCED_FLAG<<9)
 #endif
 
 #ifdef FOR_mountpoint
@@ -5654,13 +5827,13 @@
 #ifndef TT
 #define TT this.mv
 #endif
-#define FLAG_T (1<<0)
-#define FLAG_t (1<<1)
-#define FLAG_i (1<<2)
-#define FLAG_f (1<<3)
-#define FLAG_F (1<<4)
-#define FLAG_n (1<<5)
-#define FLAG_v (1<<6)
+#define FLAG_T (1LL<<0)
+#define FLAG_t (1LL<<1)
+#define FLAG_i (1LL<<2)
+#define FLAG_f (1LL<<3)
+#define FLAG_F (1LL<<4)
+#define FLAG_n (1LL<<5)
+#define FLAG_v (1LL<<6)
 #endif
 
 #ifdef FOR_nbd_client
@@ -5670,6 +5843,15 @@
 #endif
 #define FLAG_s (FORCED_FLAG<<0)
 #define FLAG_n (FORCED_FLAG<<1)
+#define FLAG_b (FORCED_FLAG<<2)
+#endif
+
+#ifdef FOR_nbd_server
+#define CLEANUP_nbd_server
+#ifndef TT
+#define TT this.nbd_server
+#endif
+#define FLAG_r (FORCED_FLAG<<0)
 #endif
 
 #ifdef FOR_netcat
@@ -5677,20 +5859,21 @@
 #ifndef TT
 #define TT this.netcat
 #endif
-#define FLAG_U (FORCED_FLAG<<0)
-#define FLAG_u (FORCED_FLAG<<1)
-#define FLAG_6 (FORCED_FLAG<<2)
-#define FLAG_4 (FORCED_FLAG<<3)
-#define FLAG_f (FORCED_FLAG<<4)
-#define FLAG_s (FORCED_FLAG<<5)
-#define FLAG_q (FORCED_FLAG<<6)
-#define FLAG_p (FORCED_FLAG<<7)
-#define FLAG_W (FORCED_FLAG<<8)
-#define FLAG_w (FORCED_FLAG<<9)
-#define FLAG_L (FORCED_FLAG<<10)
-#define FLAG_l (FORCED_FLAG<<11)
-#define FLAG_E (FORCED_FLAG<<12)
-#define FLAG_t (FORCED_FLAG<<13)
+#define FLAG_n (FORCED_FLAG<<0)
+#define FLAG_U (FORCED_FLAG<<1)
+#define FLAG_u (FORCED_FLAG<<2)
+#define FLAG_6 (FORCED_FLAG<<3)
+#define FLAG_4 (FORCED_FLAG<<4)
+#define FLAG_f (FORCED_FLAG<<5)
+#define FLAG_s (FORCED_FLAG<<6)
+#define FLAG_q (FORCED_FLAG<<7)
+#define FLAG_p (FORCED_FLAG<<8)
+#define FLAG_W (FORCED_FLAG<<9)
+#define FLAG_w (FORCED_FLAG<<10)
+#define FLAG_L (FORCED_FLAG<<11)
+#define FLAG_l (FORCED_FLAG<<12)
+#define FLAG_E (FORCED_FLAG<<13)
+#define FLAG_t (FORCED_FLAG<<14)
 #endif
 
 #ifdef FOR_netstat
@@ -5724,13 +5907,13 @@
 #ifndef TT
 #define TT this.nl
 #endif
-#define FLAG_E (1<<0)
-#define FLAG_s (1<<1)
-#define FLAG_n (1<<2)
-#define FLAG_b (1<<3)
-#define FLAG_w (1<<4)
-#define FLAG_l (1<<5)
-#define FLAG_v (1<<6)
+#define FLAG_E (1LL<<0)
+#define FLAG_s (1LL<<1)
+#define FLAG_n (1LL<<2)
+#define FLAG_b (1LL<<3)
+#define FLAG_w (1LL<<4)
+#define FLAG_l (1LL<<5)
+#define FLAG_v (1LL<<6)
 #endif
 
 #ifdef FOR_nohup
@@ -5759,8 +5942,10 @@
 #define FLAG_n (FORCED_FLAG<<3)
 #define FLAG_m (FORCED_FLAG<<4)
 #define FLAG_i (FORCED_FLAG<<5)
-#define FLAG_t (FORCED_FLAG<<6)
-#define FLAG_F (FORCED_FLAG<<7)
+#define FLAG_C (FORCED_FLAG<<6)
+#define FLAG_t (FORCED_FLAG<<7)
+#define FLAG_F (FORCED_FLAG<<8)
+#define FLAG_a (FORCED_FLAG<<9)
 #endif
 
 #ifdef FOR_od
@@ -5768,18 +5953,18 @@
 #ifndef TT
 #define TT this.od
 #endif
-#define FLAG_t (1<<0)
-#define FLAG_A (1<<1)
-#define FLAG_b (1<<2)
-#define FLAG_c (1<<3)
-#define FLAG_d (1<<4)
-#define FLAG_o (1<<5)
-#define FLAG_s (1<<6)
-#define FLAG_x (1<<7)
-#define FLAG_N (1<<8)
-#define FLAG_w (1<<9)
-#define FLAG_v (1<<10)
-#define FLAG_j (1<<11)
+#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_oneit
@@ -5826,8 +6011,8 @@
 #ifndef TT
 #define TT this.paste
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_d (1<<1)
+#define FLAG_s (1LL<<0)
+#define FLAG_d (1LL<<1)
 #endif
 
 #ifdef FOR_patch
@@ -5835,19 +6020,19 @@
 #ifndef TT
 #define TT this.patch
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_R (1<<1)
-#define FLAG_i (1<<2)
-#define FLAG_d (1<<3)
-#define FLAG_p (1<<4)
-#define FLAG_l (1<<5)
-#define FLAG_u (1<<6)
-#define FLAG_f (1<<7)
-#define FLAG_g (1<<8)
-#define FLAG_F (1<<9)
+#define FLAG_s (1LL<<0)
+#define FLAG_R (1LL<<1)
+#define FLAG_i (1LL<<2)
+#define FLAG_d (1LL<<3)
+#define FLAG_p (1LL<<4)
+#define FLAG_l (1LL<<5)
+#define FLAG_u (1LL<<6)
+#define FLAG_f (1LL<<7)
+#define FLAG_g (1LL<<8)
+#define FLAG_F (1LL<<9)
 #define FLAG_x (FORCED_FLAG<<10)
-#define FLAG_dry_run (1<<11)
-#define FLAG_no_backup_if_mismatch (1<<12)
+#define FLAG_dry_run (1LL<<11)
+#define FLAG_no_backup_if_mismatch (1LL<<12)
 #endif
 
 #ifdef FOR_pgrep
@@ -5990,8 +6175,8 @@
 #ifndef TT
 #define TT this.pwd
 #endif
-#define FLAG_P (1<<0)
-#define FLAG_L (1<<1)
+#define FLAG_P (1LL<<0)
+#define FLAG_L (1LL<<1)
 #endif
 
 #ifdef FOR_pwdx
@@ -6052,11 +6237,29 @@
 #ifndef TT
 #define TT this.readlink
 #endif
-#define FLAG_f (1<<0)
-#define FLAG_e (1<<1)
-#define FLAG_m (1<<2)
-#define FLAG_q (1<<3)
-#define FLAG_n (1<<4)
+#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 (1LL<<0)
+#define FLAG_q (1LL<<1)
+#define FLAG_m (1LL<<2)
+#define FLAG_e (1LL<<3)
+#define FLAG_P (1LL<<4)
+#define FLAG_L (1LL<<5)
+#define FLAG_s (1LL<<6)
+#define FLAG_R (1LL<<7)
+#define FLAG_relative_base (1LL<<8)
 #endif
 
 #ifdef FOR_reboot
@@ -6119,11 +6322,11 @@
 #ifndef TT
 #define TT this.rm
 #endif
-#define FLAG_v (1<<0)
-#define FLAG_r (1<<1)
-#define FLAG_R (1<<2)
-#define FLAG_i (1<<3)
-#define FLAG_f (1<<4)
+#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_rmdir
@@ -6131,8 +6334,8 @@
 #ifndef TT
 #define TT this.rmdir
 #endif
-#define FLAG_p (1<<0)
-#define FLAG_ignore_fail_on_non_empty (1<<1)
+#define FLAG_p (1LL<<0)
+#define FLAG_ignore_fail_on_non_empty (1LL<<1)
 #endif
 
 #ifdef FOR_rmmod
@@ -6183,16 +6386,17 @@
 #ifndef TT
 #define TT this.sed
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_z (1<<1)
-#define FLAG_r (1<<2)
-#define FLAG_E (1<<3)
-#define FLAG_n (1<<4)
-#define FLAG_i (1<<5)
-#define FLAG_f (1<<6)
-#define FLAG_e (1<<7)
-#define FLAG_version (1<<8)
-#define FLAG_help (1<<9)
+#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_sendevent
@@ -6207,9 +6411,9 @@
 #ifndef TT
 #define TT this.seq
 #endif
-#define FLAG_w (1<<0)
-#define FLAG_s (1<<1)
-#define FLAG_f (1<<2)
+#define FLAG_w (1LL<<0)
+#define FLAG_s (1LL<<1)
+#define FLAG_f (1LL<<2)
 #endif
 
 #ifdef FOR_set
@@ -6242,9 +6446,9 @@
 #ifndef TT
 #define TT this.setsid
 #endif
-#define FLAG_d (1<<0)
-#define FLAG_c (1<<1)
-#define FLAG_w (1<<2)
+#define FLAG_d (1LL<<0)
+#define FLAG_c (1LL<<1)
+#define FLAG_w (1LL<<2)
 #endif
 
 #ifdef FOR_sh
@@ -6291,6 +6495,16 @@
 #define FLAG_z (FORCED_FLAG<<6)
 #endif
 
+#ifdef FOR_shuf
+#define CLEANUP_shuf
+#ifndef TT
+#define TT this.shuf
+#endif
+#define FLAG_n (FORCED_FLAG<<0)
+#define FLAG_e (FORCED_FLAG<<1)
+#define FLAG_z (FORCED_FLAG<<2)
+#endif
+
 #ifdef FOR_skeleton
 #define CLEANUP_skeleton
 #ifndef TT
@@ -6301,9 +6515,12 @@
 #define FLAG_c (FORCED_FLAG<<2)
 #define FLAG_d (FORCED_FLAG<<3)
 #define FLAG_e (FORCED_FLAG<<4)
-#define FLAG_also (FORCED_FLAG<<5)
-#define FLAG_blubber (FORCED_FLAG<<6)
-#define FLAG_walrus (FORCED_FLAG<<7)
+#define FLAG_f (FORCED_FLAG<<5)
+#define FLAG_g (FORCED_FLAG<<6)
+#define FLAG_h (FORCED_FLAG<<7)
+#define FLAG_also (FORCED_FLAG<<8)
+#define FLAG_blubber (FORCED_FLAG<<9)
+#define FLAG_walrus (FORCED_FLAG<<10)
 #endif
 
 #ifdef FOR_skeleton_alias
@@ -6346,26 +6563,27 @@
 #ifndef TT
 #define TT this.sort
 #endif
-#define FLAG_n (1<<0)
-#define FLAG_u (1<<1)
-#define FLAG_r (1<<2)
-#define FLAG_i (1<<3)
-#define FLAG_f (1<<4)
-#define FLAG_d (1<<5)
-#define FLAG_z (1<<6)
-#define FLAG_s (1<<7)
-#define FLAG_c (1<<8)
-#define FLAG_M (1<<9)
-#define FLAG_b (1<<10)
-#define FLAG_V (1<<11)
-#define FLAG_x (1<<12)
-#define FLAG_t (1<<13)
-#define FLAG_k (1<<14)
-#define FLAG_o (1<<15)
-#define FLAG_m (1<<16)
-#define FLAG_T (1<<17)
-#define FLAG_S (1<<18)
-#define FLAG_g (1<<19)
+#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 (1LL<<20)
 #endif
 
 #ifdef FOR_source
@@ -6391,10 +6609,10 @@
 #ifndef TT
 #define TT this.stat
 #endif
-#define FLAG_t (1<<0)
-#define FLAG_L (1<<1)
-#define FLAG_f (1<<2)
-#define FLAG_c (1<<3)
+#define FLAG_t (1LL<<0)
+#define FLAG_L (1LL<<1)
+#define FLAG_f (1LL<<2)
+#define FLAG_c (1LL<<3)
 #endif
 
 #ifdef FOR_strace
@@ -6456,6 +6674,8 @@
 #ifndef TT
 #define TT this.swapoff
 #endif
+#define FLAG_v (FORCED_FLAG<<0)
+#define FLAG_a (FORCED_FLAG<<1)
 #endif
 
 #ifdef FOR_swapon
@@ -6531,11 +6751,11 @@
 #ifndef TT
 #define TT this.tail
 #endif
-#define FLAG_n (1<<0)
-#define FLAG_c (1<<1)
-#define FLAG_s (1<<2)
-#define FLAG_F (1<<3)
-#define FLAG_f (1<<4)
+#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_tar
@@ -6543,41 +6763,54 @@
 #ifndef TT
 #define TT this.tar
 #endif
-#define FLAG_a (1<<0)
-#define FLAG_f (1<<1)
-#define FLAG_C (1<<2)
-#define FLAG_T (1<<3)
-#define FLAG_X (1<<4)
-#define FLAG_m (1<<5)
-#define FLAG_P (1<<6)
-#define FLAG_O (1<<7)
-#define FLAG_S (1<<8)
-#define FLAG_z (1<<9)
-#define FLAG_j (1<<10)
-#define FLAG_J (1<<11)
-#define FLAG_I (1<<12)
-#define FLAG_v (1<<13)
-#define FLAG_t (1<<14)
-#define FLAG_x (1<<15)
-#define FLAG_h (1<<16)
-#define FLAG_c (1<<17)
-#define FLAG_k (1<<18)
-#define FLAG_p (1<<19)
-#define FLAG_o (1<<20)
-#define FLAG_to_command (1<<21)
-#define FLAG_owner (1<<22)
-#define FLAG_group (1<<23)
-#define FLAG_mtime (1<<24)
-#define FLAG_mode (1<<25)
-#define FLAG_exclude (1<<26)
-#define FLAG_overwrite (1<<27)
-#define FLAG_no_same_permissions (1<<28)
-#define FLAG_numeric_owner (1<<29)
-#define FLAG_no_recursion (1<<30)
-#define FLAG_full_time (1LL<<31)
-#define FLAG_restrict (1LL<<32)
-#define FLAG_selinux (1LL<<33)
-#define FLAG_strip_components (1LL<<34)
+#define FLAG_s (1LL<<0)
+#define FLAG_a (1LL<<1)
+#define FLAG_f (1LL<<2)
+#define FLAG_C (1LL<<3)
+#define FLAG_I (1LL<<4)
+#define FLAG_T (1LL<<5)
+#define FLAG_X (1LL<<6)
+#define FLAG_m (1LL<<7)
+#define FLAG_P (1LL<<8)
+#define FLAG_O (1LL<<9)
+#define FLAG_S (1LL<<10)
+#define FLAG_z (1LL<<11)
+#define FLAG_j (1LL<<12)
+#define FLAG_J (1LL<<13)
+#define FLAG_v (1LL<<14)
+#define FLAG_t (1LL<<15)
+#define FLAG_x (1LL<<16)
+#define FLAG_h (1LL<<17)
+#define FLAG_c (1LL<<18)
+#define FLAG_k (1LL<<19)
+#define FLAG_p (1LL<<20)
+#define FLAG_o (1LL<<21)
+#define FLAG_xform (1LL<<22)
+#define FLAG_strip (1LL<<23)
+#define FLAG_to_command (1LL<<24)
+#define FLAG_owner (1LL<<25)
+#define FLAG_group (1LL<<26)
+#define FLAG_mtime (1LL<<27)
+#define FLAG_mode (1LL<<28)
+#define FLAG_sort (1LL<<29)
+#define FLAG_exclude (1LL<<30)
+#define FLAG_overwrite (1LL<<31)
+#define FLAG_no_same_permissions (1LL<<32)
+#define FLAG_numeric_owner (1LL<<33)
+#define FLAG_null (1LL<<34)
+#define FLAG_no_recursion (1LL<<35)
+#define FLAG_full_time (1LL<<36)
+#define FLAG_restrict (1LL<<37)
+#define FLAG_selinux (1LL<<38)
+#define FLAG_show_transformed_names (1LL<<39)
+#define FLAG_wildcards_match_slash (1LL<<40)
+#define FLAG_no_wildcards_match_slash (1LL<<41)
+#define FLAG_wildcards (1LL<<42)
+#define FLAG_no_wildcards (1LL<<43)
+#define FLAG_anchored (1LL<<44)
+#define FLAG_no_anchored (1LL<<45)
+#define FLAG_ignore_case (1LL<<46)
+#define FLAG_no_ignore_case (1LL<<47)
 #endif
 
 #ifdef FOR_taskset
@@ -6599,8 +6832,8 @@
 #define FLAG_h (FORCED_FLAG<<2)
 #define FLAG_l (FORCED_FLAG<<3)
 #define FLAG_u (FORCED_FLAG<<4)
-#define FLAG_b (FORCED_FLAG<<5)
-#define FLAG_C (FORCED_FLAG<<6)
+#define FLAG_C (FORCED_FLAG<<5)
+#define FLAG_b (FORCED_FLAG<<6)
 #define FLAG_c (FORCED_FLAG<<7)
 #endif
 
@@ -6609,8 +6842,8 @@
 #ifndef TT
 #define TT this.tee
 #endif
-#define FLAG_a (1<<0)
-#define FLAG_i (1<<1)
+#define FLAG_a (1LL<<0)
+#define FLAG_i (1LL<<1)
 #endif
 
 #ifdef FOR_telnet
@@ -6680,11 +6913,12 @@
 #ifndef TT
 #define TT this.timeout
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_k (1<<1)
-#define FLAG_v (1<<2)
-#define FLAG_preserve_status (1<<3)
-#define FLAG_foreground (1<<4)
+#define FLAG_i (1LL<<0)
+#define FLAG_s (1LL<<1)
+#define FLAG_k (1LL<<2)
+#define FLAG_v (1LL<<3)
+#define FLAG_preserve_status (1LL<<4)
+#define FLAG_foreground (1LL<<5)
 #endif
 
 #ifdef FOR_top
@@ -6712,14 +6946,14 @@
 #ifndef TT
 #define TT this.touch
 #endif
-#define FLAG_h (1<<0)
-#define FLAG_t (1<<1)
-#define FLAG_r (1<<2)
-#define FLAG_m (1<<3)
-#define FLAG_f (1<<4)
-#define FLAG_d (1<<5)
-#define FLAG_c (1<<6)
-#define FLAG_a (1<<7)
+#define FLAG_h (1LL<<0)
+#define FLAG_t (1LL<<1)
+#define FLAG_r (1LL<<2)
+#define FLAG_m (1LL<<3)
+#define FLAG_f (1LL<<4)
+#define FLAG_d (1LL<<5)
+#define FLAG_c (1LL<<6)
+#define FLAG_a (1LL<<7)
 #endif
 
 #ifdef FOR_toybox
@@ -6734,10 +6968,10 @@
 #ifndef TT
 #define TT this.tr
 #endif
-#define FLAG_d (1<<0)
-#define FLAG_s (1<<1)
-#define FLAG_c (1<<2)
-#define FLAG_C (1<<3)
+#define FLAG_d (1LL<<0)
+#define FLAG_s (1LL<<1)
+#define FLAG_c (1LL<<2)
+#define FLAG_C (1LL<<3)
 #endif
 
 #ifdef FOR_traceroute
@@ -6779,8 +7013,8 @@
 #ifndef TT
 #define TT this.truncate
 #endif
-#define FLAG_c (1<<0)
-#define FLAG_s (1<<1)
+#define FLAG_c (1LL<<0)
+#define FLAG_s (1LL<<1)
 #endif
 
 #ifdef FOR_tty
@@ -6863,13 +7097,14 @@
 #ifndef TT
 #define TT this.uname
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_n (1<<1)
-#define FLAG_r (1<<2)
-#define FLAG_v (1<<3)
-#define FLAG_m (1<<4)
-#define FLAG_o (1<<5)
-#define FLAG_a (1<<6)
+#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_unicode
@@ -6884,14 +7119,14 @@
 #ifndef TT
 #define TT this.uniq
 #endif
-#define FLAG_u (1<<0)
-#define FLAG_d (1<<1)
-#define FLAG_c (1<<2)
-#define FLAG_i (1<<3)
-#define FLAG_z (1<<4)
-#define FLAG_w (1<<5)
-#define FLAG_s (1<<6)
-#define FLAG_f (1<<7)
+#define FLAG_u (1LL<<0)
+#define FLAG_d (1LL<<1)
+#define FLAG_c (1LL<<2)
+#define FLAG_i (1LL<<3)
+#define FLAG_z (1LL<<4)
+#define FLAG_w (1LL<<5)
+#define FLAG_s (1LL<<6)
+#define FLAG_f (1LL<<7)
 #endif
 
 #ifdef FOR_unix2dos
@@ -6929,8 +7164,10 @@
 #define FLAG_n (FORCED_FLAG<<3)
 #define FLAG_m (FORCED_FLAG<<4)
 #define FLAG_i (FORCED_FLAG<<5)
-#define FLAG_r (FORCED_FLAG<<6)
-#define FLAG_f (FORCED_FLAG<<7)
+#define FLAG_C (FORCED_FLAG<<6)
+#define FLAG_r (FORCED_FLAG<<7)
+#define FLAG_f (FORCED_FLAG<<8)
+#define FLAG_a (FORCED_FLAG<<9)
 #endif
 
 #ifdef FOR_uptime
@@ -7061,10 +7298,10 @@
 #ifndef TT
 #define TT this.wc
 #endif
-#define FLAG_l (1<<0)
-#define FLAG_w (1<<1)
-#define FLAG_c (1<<2)
-#define FLAG_m (1<<3)
+#define FLAG_l (1LL<<0)
+#define FLAG_w (1LL<<1)
+#define FLAG_c (1LL<<2)
+#define FLAG_m (1LL<<3)
 #endif
 
 #ifdef FOR_wget
@@ -7083,7 +7320,7 @@
 #ifndef TT
 #define TT this.which
 #endif
-#define FLAG_a (1<<0)
+#define FLAG_a (1LL<<0)
 #endif
 
 #ifdef FOR_who
@@ -7099,15 +7336,15 @@
 #ifndef TT
 #define TT this.xargs
 #endif
-#define FLAG_0 (1<<0)
-#define FLAG_s (1<<1)
-#define FLAG_n (1<<2)
-#define FLAG_r (1<<3)
-#define FLAG_t (1<<4)
-#define FLAG_p (1<<5)
-#define FLAG_o (1<<6)
-#define FLAG_P (1<<7)
-#define FLAG_E (1<<8)
+#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
 
 #ifdef FOR_xxd
@@ -7115,14 +7352,15 @@
 #ifndef TT
 #define TT this.xxd
 #endif
-#define FLAG_s (1<<0)
-#define FLAG_r (1<<1)
-#define FLAG_p (1<<2)
-#define FLAG_i (1<<3)
-#define FLAG_g (1<<4)
-#define FLAG_o (1<<5)
-#define FLAG_l (1<<6)
-#define FLAG_c (1<<7)
+#define FLAG_s (1LL<<0)
+#define FLAG_r (1LL<<1)
+#define FLAG_p (1LL<<2)
+#define FLAG_i (1LL<<3)
+#define FLAG_e (1LL<<4)
+#define FLAG_g (1LL<<5)
+#define FLAG_o (1LL<<6)
+#define FLAG_l (1LL<<7)
+#define FLAG_c (1LL<<8)
 #endif
 
 #ifdef FOR_xzcat
@@ -7144,18 +7382,19 @@
 #ifndef TT
 #define TT this.zcat
 #endif
-#define FLAG_9 (1<<0)
-#define FLAG_8 (1<<1)
-#define FLAG_7 (1<<2)
-#define FLAG_6 (1<<3)
-#define FLAG_5 (1<<4)
-#define FLAG_4 (1<<5)
-#define FLAG_3 (1<<6)
-#define FLAG_2 (1<<7)
-#define FLAG_1 (1<<8)
-#define FLAG_k (1<<9)
-#define FLAG_f (1<<10)
-#define FLAG_d (1<<11)
-#define FLAG_c (1<<12)
+#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)
 #endif
 
diff --git a/android/mac/generated/globals.h b/android/mac/generated/globals.h
index 403077b..2b646d0 100644
--- a/android/mac/generated/globals.h
+++ b/android/mac/generated/globals.h
@@ -2,6 +2,8 @@
 
 struct log_data {
   char *t, *p;
+
+  int pri;
 };
 
 // toys/example/demo_number.c
@@ -25,7 +27,7 @@
       long c;
       struct arg_list *d;
       long e;
-      char *also, *blubber;
+      char *f, *g, *h, *also, *blubber;
     } s;
     struct {
       long b;
@@ -99,9 +101,8 @@
 // toys/lsb/mount.c
 
 struct mount_data {
-  struct arg_list *optlist;
-  char *type;
-  char *bigO;
+  struct arg_list *o;
+  char *t, *O;
 
   unsigned long flags;
   char *opts;
@@ -213,6 +214,22 @@
   char *u;
 };
 
+// toys/net/wget.c
+
+struct wget_data {
+  char *p, *O;
+  long max_redirect;
+
+  int sock, https;
+  char *url;
+#if CFG_WGET_LIBTLS
+  struct tls *tls;
+#elif CFG_TOYBOX_LIBCRYPTO
+  struct ssl_ctx_st *ctx;
+  struct ssl_st *ssl;
+#endif
+};
+
 // toys/other/acpi.c
 
 struct acpi_data {
@@ -224,6 +241,7 @@
 
 struct base64_data {
   long w;
+
   unsigned total;
   unsigned n;  // number of bits used in encoding. 5 for base32, 6 for base64
   unsigned align;  // number of bits to align to
@@ -239,6 +257,7 @@
 
 struct blkid_data {
   struct arg_list *s;
+  char *o;
 };
 
 // toys/other/blockdev.c
@@ -268,7 +287,7 @@
 // toys/other/fmt.c
 
 struct fmt_data {
-  int width;
+  long width;
 
   int level, pos;
 };
@@ -343,7 +362,7 @@
 
 struct lsusb_data {
   char *i;
-  long n;
+  long x, n;
 
   void *ids, *class;
   int count;
@@ -384,10 +403,18 @@
   int count;
 };
 
+// toys/other/nbd_client.c
+
+struct nbd_client_data {
+  long b;
+
+  int nbd;
+};
+
 // toys/other/nsenter.c
 
 struct nsenter_data {
-  char *Uupnmi[6];
+  char *UupnmiC[6];
   long t;
 };
 
@@ -419,6 +446,12 @@
   int bits, endian, shnum, shentsize, phentsize;
 };
 
+// toys/other/readlink.c
+
+struct readlink_data {
+  char *R, *relative_base;
+};
+
 // toys/other/reboot.c
 
 struct reboot_data {
@@ -451,6 +484,15 @@
   long o, n, s;
 };
 
+// toys/other/shuf.c
+
+struct shuf_data {
+  long n;
+
+  char **lines;
+  long count;
+};
+
 // toys/other/stat.c
 
 struct stat_data {
@@ -489,11 +531,9 @@
 struct timeout_data {
   char *s, *k;
 
-  int nextsig;
-  pid_t pid;
-  struct timespec kts;
-  struct itimerspec its;
-  timer_t timer;
+  struct pollfd pfd;
+  sigjmp_buf sj;
+  int fds[2], pid;
 };
 
 // toys/other/truncate.c
@@ -616,8 +656,7 @@
 
 struct dd_data {
   int show_xfer, show_records;
-  unsigned long long bytes, c_count, in_full, in_part, out_full, out_part;
-  struct timeval start;
+  unsigned long long bytes, in_full, in_part, out_full, out_part, start;
   struct {
     char *name;
     int fd;
@@ -667,13 +706,20 @@
 // toys/pending/diff.c
 
 struct diff_data {
-  long ct;
-  char *start;
-  struct arg_list *L_list;
+  long U;
+  struct arg_list *L;
+  char *F, *S, *new_line_format, *old_line_format, *unchanged_line_format;
 
-  int dir_num, size, is_binary, status, change, len[2];
-  int *offset[2];
+  int dir_num, size, is_binary, differ, change, len[2], *offset[2];
   struct stat st[2];
+  struct {
+    char **list;
+    int nr_elm;
+  } dir[2];
+  struct {
+    FILE *fp;
+    int len;
+  } file[2];
 };
 
 // toys/pending/dumpleases.c
@@ -745,6 +791,13 @@
   struct termios termios;
 };
 
+// toys/pending/git.c
+
+struct git_data {
+  char *url, *name; //git repo remote url and init directory name
+  struct IndexV2 *i; //git creates a index for each pack file, git clone just needs one index for the received pack file
+};
+
 // toys/pending/groupadd.c
 
 struct groupadd_data {
@@ -890,7 +943,7 @@
   long long SECONDS;
   char *isexec, *wcpat;
   unsigned options, jobcnt, LINENO;
-  int hfd, pid, bangpid, varslen, srclvl, recursion;
+  int hfd, pid, bangpid, srclvl, recursion;
 
   // Callable function array
   struct sh_function {
@@ -916,11 +969,11 @@
       long flags;
       char *str;
     } *vars;
-    long varslen, shift;
+    long varslen, varscap, shift, oldlineno;
 
     struct sh_function *func; // TODO wire this up
     struct sh_pipeline *pl;
-    char *ifs;
+    char *ifs, *omnom;
     struct sh_arg arg;
     struct arg_list *delete;
 
@@ -998,11 +1051,8 @@
 // toys/pending/tcpsvd.c
 
 struct tcpsvd_data {
-  char *name;
-  char *user;
-  long bn;
-  char *nmsg;
-  long cn;
+  char *l, *u, *C;
+  long b, c;
 
   int maxc;
   int count_all;
@@ -1100,6 +1150,8 @@
 
 struct vi_data {
   char *s;
+
+  char *filename;
   int vi_mode, tabstop, list;
   int cur_col, cur_row, scr_row;
   int drawn_row, drawn_col;
@@ -1119,13 +1171,9 @@
     char* data;
   } yank;
 
-  int modified;
   size_t filesize;
 // mem_block contains RO data that is either original file as mmap
 // or heap allocated inserted data
-//
-//
-//
   struct block_list {
     struct block_list *next, *prev;
     struct mem_block {
@@ -1156,22 +1204,6 @@
   } *slices;
 };
 
-// toys/pending/wget.c
-
-struct wget_data {
-  char *p, *O;
-  long max_redirect;
-
-  int sock, https;
-  char *url;
-#if CFG_WGET_LIBTLS
-  struct tls *tls;
-#elif CFG_WGET_OPENSSL
-  struct ssl_ctx_st *ctx;
-  struct ssl_st *ssl;
-#endif
-};
-
 // toys/posix/basename.c
 
 struct basename_data {
@@ -1239,7 +1271,7 @@
 // toys/posix/cpio.c
 
 struct cpio_data {
-  char *F, *H;
+  char *F, *H, *R;
 };
 
 // toys/posix/cut.c
@@ -1320,8 +1352,8 @@
 
   char *purple, *cyan, *red, *green, *grey;
   struct double_list *reg;
-  char indelim, outdelim;
-  int found, tried;
+  int found, tried, delim;
+  struct arg_list *fixed[256];
 };
 
 // toys/posix/head.c
@@ -1363,14 +1395,15 @@
 
 struct logger_data {
   char *p, *t;
+
+  int priority;
 };
 
 // toys/posix/ls.c
 
 struct ls_data {
-  long w;
-  long l;
-  char *color;
+  long w, l;
+  char *color, *sort;
 
   struct dirtree *files, *singledir;
   unsigned screen_width;
@@ -1465,7 +1498,10 @@
     } pgrep;
   };
 
-  struct ptr_len gg, GG, pp, PP, ss, tt, uu, UU;
+  struct ps_ptr_len {
+    void *ptr;
+    long len;
+  } gg, GG, pp, PP, ss, tt, uu, UU;
   struct dirtree *threadparent;
   unsigned width, height, scroll;
   dev_t tty;
@@ -1491,12 +1527,12 @@
   // processed pattern list
   struct double_list *pattern;
 
-  char *nextline, *remember;
+  char *nextline, *remember, *tarxform;
   void *restart, *lastregex;
   long nextlen, rememberlen, count;
   int fdout, noeol;
-  unsigned xx;
-  char delim;
+  unsigned xx, tarxlen, xflags;
+  char delim, xftype;
 };
 
 // toys/posix/sort.c
@@ -1537,32 +1573,31 @@
   struct {
     char *path;
     int fd;
-    dev_t dev;
-    ino_t ino;
+    struct dev_ino di;
   } *F;
 };
 
 // toys/posix/tar.c
 
 struct tar_data {
-  char *f, *C;
-  struct arg_list *T, *X;
-  char *I, *to_command, *owner, *group, *mtime, *mode;
+  char *f, *C, *I;
+  struct arg_list *T, *X, *xform;
+  long strip;
+  char *to_command, *owner, *group, *mtime, *mode, *sort;
   struct arg_list *exclude;
-  long strip_components;
 
   struct double_list *incl, *excl, *seen;
   struct string_list *dirs;
-  char *cwd;
-  int fd, ouid, ggid, hlc, warn, adev, aino, sparselen, pid;
+  char *cwd, **xfsed;
+  int fd, ouid, ggid, hlc, warn, sparselen, pid, xfpipe[2];
+  struct dev_ino archive_di;
   long long *sparse;
   time_t mtt;
 
   // hardlinks seen so far (hlc many)
   struct {
     char *arg;
-    ino_t ino;
-    dev_t dev;
+    struct dev_ino di;
   } *hlx;
 
   // Parsed information about a tar header.
@@ -1654,6 +1689,7 @@
 	struct ping_data ping;
 	struct sntp_data sntp;
 	struct tunctl_data tunctl;
+	struct wget_data wget;
 	struct acpi_data acpi;
 	struct base64_data base64;
 	struct blkdiscard_data blkdiscard;
@@ -1677,16 +1713,19 @@
 	struct mkpasswd_data mkpasswd;
 	struct mkswap_data mkswap;
 	struct modinfo_data modinfo;
+	struct nbd_client_data nbd_client;
 	struct nsenter_data nsenter;
 	struct oneit_data oneit;
 	struct openvt_data openvt;
 	struct pwgen_data pwgen;
 	struct readelf_data readelf;
+	struct readlink_data readlink;
 	struct reboot_data reboot;
 	struct rtcwake_data rtcwake;
 	struct setfattr_data setfattr;
 	struct sha3sum_data sha3sum;
 	struct shred_data shred;
+	struct shuf_data shuf;
 	struct stat_data stat;
 	struct swapon_data swapon;
 	struct switch_root_data switch_root;
@@ -1718,6 +1757,7 @@
 	struct getfattr_data getfattr;
 	struct getopt_data getopt;
 	struct getty_data getty;
+	struct git_data git;
 	struct groupadd_data groupadd;
 	struct hexdump_data hexdump;
 	struct ip_data ip;
@@ -1745,7 +1785,6 @@
 	struct traceroute_data traceroute;
 	struct useradd_data useradd;
 	struct vi_data vi;
-	struct wget_data wget;
 	struct basename_data basename;
 	struct cal_data cal;
 	struct chgrp_data chgrp;
diff --git a/android/mac/generated/help.h b/android/mac/generated/help.h
index 30c24e9..aef8828 100644
--- a/android/mac/generated/help.h
+++ b/android/mac/generated/help.h
@@ -104,15 +104,19 @@
 
 #define HELP_zcat "usage: zcat [FILE...]\n\nDecompress files to stdout. Like `gzip -dc`.\n\n-f	Force: allow read from tty"
 
-#define HELP_gunzip "usage: gunzip [-cfk] [FILE...]\n\nDecompress files. With no files, decompresses stdin to stdout.\nOn success, the input files are removed and replaced by new\nfiles without the .gz suffix.\n\n-c	Output to stdout (act as zcat)\n-f	Force: allow read from tty\n-k	Keep input files (default is to remove)"
+#define HELP_gunzip "usage: gunzip [-cfkt] [FILE...]\n\nDecompress files. With no files, decompresses stdin to stdout.\nOn success, the input files are removed and replaced by new\nfiles without the .gz suffix.\n\n-c	Output to stdout (act as zcat)\n-f	Force: allow read from tty\n-k	Keep input files (default is to remove)\n-t	Test integrity"
 
-#define HELP_gzip "usage: gzip [-19cdfk] [FILE...]\n\nCompress files. With no files, compresses stdin to stdout.\nOn success, the input files are removed and replaced by new\nfiles with the .gz suffix.\n\n-c	Output to stdout\n-d	Decompress (act as gunzip)\n-f	Force: allow overwrite of output file\n-k	Keep input files (default is to remove)\n-#	Compression level 1-9 (1:fastest, 6:default, 9:best)"
+#define HELP_gzip "usage: gzip [-19cdfkt] [FILE...]\n\nCompress files. With no files, compresses stdin to stdout.\nOn success, the input files are removed and replaced by new\nfiles with the .gz suffix.\n\n-c	Output to stdout\n-d	Decompress (act as gunzip)\n-f	Force: allow overwrite of output file\n-k	Keep input files (default is to remove)\n-t	Test integrity\n-#	Compression level 1-9 (1:fastest, 6:default, 9:best)"
 
 #define HELP_dmesg "usage: dmesg [-Cc] [-r|-t|-T] [-n LEVEL] [-s SIZE] [-w]\n\nPrint or control the kernel ring buffer.\n\n-C	Clear ring buffer without printing\n-c	Clear ring buffer after printing\n-n	Set kernel logging LEVEL (1-9)\n-r	Raw output (with <level markers>)\n-S	Use syslog(2) rather than /dev/kmsg\n-s	Show the last SIZE many bytes\n-T	Human readable timestamps\n-t	Don't print timestamps\n-w	Keep waiting for more output (aka --follow)"
 
+#define HELP_wget_libtls "Enable HTTPS support for wget by linking to LibTLS.\nSupports using libtls, libretls or libtls-bearssl.\n\nUse TOYBOX_LIBCRYPTO to enable HTTPS support via OpenSSL."
+
+#define HELP_wget "usage: wget [OPTIONS]... [URL]\n    --max-redirect          maximum redirections allowed\n-d, --debug                 print lots of debugging information\n-O, --output-document=FILE  specify output filename\n-p, --post-data=DATA        send data in body of POST request\n\nexamples:\n  wget http://www.example.com"
+
 #define HELP_tunctl "usage: tunctl [-dtT] [-u USER] NAME\n\nCreate and delete tun/tap virtual ethernet devices.\n\n-T	Use tap (ethernet frames) instead of tun (ip packets)\n-d	Delete tun/tap device\n-t	Create tun/tap device\n-u	Set owner (user who can read/write device without root access)"
 
-#define HELP_sntp "usage: sntp [-saSdDq] [-r SHIFT] [-mM[ADDRESS]] [-p PORT] [SERVER]\n\nSimple Network Time Protocol client. Query SERVER and display time.\n\n-p	Use PORT (default 123)\n-s	Set system clock suddenly\n-a	Adjust system clock gradually\n-S	Serve time instead of querying (bind to SERVER address if specified)\n-m	Wait for updates from multicast ADDRESS (RFC 4330 default 224.0.1.1)\n-M	Multicast server on ADDRESS (default 224.0.0.1)\n-t	TTL (multicast only, default 1)\n-d	Daemonize (run in background re-querying )\n-D	Daemonize but stay in foreground: re-query time every 1000 seconds\n-r	Retry shift (every 1<<SHIFT seconds)\n-q	Quiet (don't display time)"
+#define HELP_sntp "usage: sntp [-saSdDq] [-r SHIFT] [-mM[ADDRESS]] [-p PORT] [SERVER]\n\nSimple Network Time Protocol client. Query SERVER and display time.\n\n-p	Use PORT (default 123)\n-s	Set system clock suddenly\n-a	Adjust system clock gradually\n-S	Serve time instead of querying (bind to SERVER address if specified)\n-m	Wait for updates from multicast ADDRESS (RFC 4330 suggests 224.0.1.1)\n-M	Multicast server on ADDRESS (RFC 4330 suggests 224.0.1.1)\n-t	TTL (multicast only, default 1)\n-d	Daemonize (run in background re-querying)\n-D	Daemonize but stay in foreground: re-query time every 1000 seconds\n-r	Retry shift (every 1<<SHIFT seconds)\n-q	Quiet (don't display time)"
 
 #define HELP_rfkill "usage: rfkill COMMAND [DEVICE]\n\nEnable/disable wireless devices.\n\nCommands:\nlist [DEVICE]   List current state\nblock DEVICE    Disable device\nunblock DEVICE  Enable device\n\nDEVICE is an index number, or one of:\nall, wlan(wifi), bluetooth, uwb(ultrawideband), wimax, wwan, gps, fm."
 
@@ -120,14 +124,14 @@
 
 #define HELP_netstat "usage: netstat [-pWrxwutneal]\n\nDisplay networking information. Default is netstat -tuwx\n\n-r	Routing table\n-a	All sockets (not just connected)\n-l	Listening server sockets\n-t	TCP sockets\n-u	UDP sockets\n-w	Raw sockets\n-x	Unix sockets\n-e	Extended info\n-n	Don't resolve names\n-W	Wide display\n-p	Show PID/program name of sockets"
 
-#define HELP_netcat_listen "usage: netcat [-tElL]\n\n-l	Listen for one incoming connection, then exit\n-L	Listen and background each incoming connection (server mode)\n-t	Allocate tty\n-E	Forward stderr\n\nWhen listening the COMMAND line is executed as a child process to handle\nan incoming connection. With no COMMAND -l forwards the connection\nto stdin/stdout. If no -p specified, -l prints the port it bound to and\nbackgrounds itself (returning immediately).\n\nFor a quick-and-dirty server, try something like:\nnetcat -s 127.0.0.1 -p 1234 -tL sh -l"
-
-#define HELP_netcat "usage: netcat [-46U] [-u] [-wpq #] [-s addr] {IPADDR PORTNUM|-f FILENAME|COMMAND...}\n\nForward stdin/stdout to a file or network connection.\n\n-4	Force IPv4\n-6	Force IPv6\n-f	Use FILENAME (ala /dev/ttyS0) instead of network\n-p	Local port number\n-q	Quit SECONDS after EOF on stdin, even if stdout hasn't closed yet\n-s	Local source address\n-u	Use UDP\n-U	Use a UNIX domain socket\n-w	SECONDS timeout to establish connection\n-W	SECONDS timeout for more data on an idle connection\n\nUse \"stty 115200 -F /dev/ttyS0 && stty raw -echo -ctlecho\" with\nnetcat -f to connect to a serial port."
+#define HELP_netcat "usage: netcat [-46ElLtUu] [-wpq #] [-s addr] {IPADDR PORTNUM|-f FILENAME|COMMAND...}\n\nForward stdin/stdout to a file or network connection.\n\n-4	Force IPv4\n-6	Force IPv6\n-E	Forward stderr\n-f	Use FILENAME (ala /dev/ttyS0) instead of network\n-l	Listen for one incoming connection, then exit\n-L	Listen and background each incoming connection (server mode)\n-n	No DNS lookup\n-p	Local port number\n-q	Quit SECONDS after EOF on stdin, even if stdout hasn't closed yet\n-s	Local source address\n-t	Allocate tty\n-u	Use UDP\n-U	Use a UNIX domain socket\n-w	SECONDS timeout to establish connection\n-W	SECONDS timeout for more data on an idle connection\n\nWhen listening the COMMAND line is executed as a child process to handle\nan incoming connection. With no COMMAND -l forwards the connection\nto stdin/stdout. If no -p specified, -l prints the port it bound to and\nbackgrounds itself (returning immediately).\n\nFor a quick-and-dirty server, try something like:\nnetcat -s 127.0.0.1 -p 1234 -tL sh -l\n\nOr use \"stty 115200 -F /dev/ttyS0 && stty raw -echo -ctlecho\" with\nnetcat -f to connect to a serial port."
 
 #define HELP_microcom "usage: microcom [-s SPEED] [-X] DEVICE\n\nSimple serial console.\n\n-s	Set baud rate to SPEED (default 115200)\n-X	Ignore ^@ (send break) and ^] (exit)"
 
 #define HELP_ifconfig "usage: ifconfig [-aS] [INTERFACE [ACTION...]]\n\nDisplay or configure network interface.\n\nWith no arguments, display active interfaces. First argument is interface\nto operate on, one argument by itself displays that interface.\n\n-a	All interfaces displayed, not just active ones\n-S	Short view, one line per interface\n\nStandard ACTIONs to perform on an INTERFACE:\n\nADDR[/MASK]        - set IPv4 address (1.2.3.4/5) and activate interface\nadd|del ADDR[/LEN] - add/remove IPv6 address (1111::8888/128)\nup|down            - activate or deactivate interface\n\nAdvanced ACTIONs (default values usually suffice):\n\ndefault          - remove IPv4 address\nnetmask ADDR     - set IPv4 netmask via 255.255.255.0 instead of /24\ntxqueuelen LEN   - number of buffered packets before output blocks\nmtu LEN          - size of outgoing packets (Maximum Transmission Unit)\nbroadcast ADDR   - Set broadcast address\npointopoint ADDR - PPP and PPPOE use this instead of \"route add default gw\"\nhw TYPE ADDR     - set hardware (mac) address (type = ether|infiniband)\nrename NEWNAME   - rename interface\n\nFlags you can set on an interface (or -remove by prefixing with -):\n\narp       - don't use Address Resolution Protocol to map LAN routes\npromisc   - don't discard packets that aren't to this LAN hardware address\nmulticast - force interface into multicast mode if the driver doesn't\nallmulti  - promisc for multicast packets"
 
+#define HELP_httpd "usage: httpd [-e STR] [DIR]\n\nServe contents of directory as static web pages.\n\n-e	Escape STR as URL, printing result and exiting.\n-d	Decode escaped STR, printing result and exiting.\n-v	Verbose"
+
 #define HELP_host "usage: host [-v] [-t TYPE] NAME [SERVER]\n\nLook up DNS records for NAME, either domain name or IPv4/IPv6 address to\nreverse lookup, from SERVER or default DNS server(s).\n\n-a	All records\n-t TYPE	Record TYPE (number or ANY A AAAA CNAME MX NS PTR SOA SRV TXT)\n-v	Verbose"
 
 #define HELP_ftpput "An ftpget that defaults to -s instead of -g"
@@ -136,7 +140,7 @@
 
 #define HELP_yes "usage: yes [args...]\n\nRepeatedly output line until killed. If no args, output 'y'."
 
-#define HELP_xxd "usage: xxd [-c n] [-g n] [-i] [-l n] [-o n] [-p] [-r] [-s n] [file]\n\nHexdump a file to stdout. If no file is listed, copy from stdin.\nFilename \"-\" is a synonym for stdin.\n\n-c n	Show n bytes per line (default 16)\n-g n	Group bytes by adding a ' ' every n bytes (default 2)\n-i	Output include file (CSV hex bytes, plus C header/footer if not stdin)\n-l n	Limit of n bytes before stopping (default is no limit)\n-o n	Add n to display offset\n-p	Plain hexdump (30 bytes/line, no grouping)\n-r	Reverse operation: turn a hexdump into a binary file\n-s n	Skip to offset n"
+#define HELP_xxd "usage: xxd [-eipr] [-cglos N] [file]\n\nHexdump a file to stdout. If no file is listed, copy from stdin.\nFilename \"-\" is a synonym for stdin.\n\n-c N	Show N bytes per line (default 16)\n-e	Little-endian\n-g N	Group bytes by adding a ' ' every N bytes (default 2)\n-i	Output include file (CSV hex bytes, plus C header/footer if not stdin)\n-l N	Limit of N bytes before stopping (default is no limit)\n-o N	Add N to display offset\n-p	Plain hexdump (30 bytes/line, no grouping. With -c 0 no wrap/group)\n-r	Reverse operation: turn a hexdump into a binary file\n-s N	Skip to offset N"
 
 #define HELP_which "usage: which [-a] filename ...\n\nSearch $PATH for executable files matching filename(s).\n\n-a	Show all matches"
 
@@ -160,7 +164,7 @@
 
 #define HELP_truncate "usage: truncate [-c] -s SIZE file...\n\nSet length of file(s), extending sparsely if necessary.\n\n-c	Don't create file if it doesn't exist\n-s	New size (with optional prefix and suffix)\n\nSIZE prefix: + add, - subtract, < shrink to, > expand to,\n             / multiple rounding down, % multiple rounding up\nSIZE suffix: k=1024, m=1024^2, g=1024^3, t=1024^4, p=1024^5, e=1024^6"
 
-#define HELP_timeout "usage: timeout [-k DURATION] [-s SIGNAL] DURATION COMMAND...\n\nRun command line as a child process, sending child a signal if the\ncommand doesn't exit soon enough.\n\nDURATION can be a decimal fraction. An optional suffix can be \"m\"\n(minutes), \"h\" (hours), \"d\" (days), or \"s\" (seconds, the default).\n\n-s	Send specified signal (default TERM)\n-k	Send KILL signal if child still running this long after first signal\n-v	Verbose\n--foreground       Don't create new process group\n--preserve-status  Exit with the child's exit status"
+#define HELP_timeout "usage: timeout [-i] [-k DURATION] [-s SIGNAL] DURATION COMMAND...\n\nRun command line as a child process, sending child a signal if the\ncommand doesn't exit soon enough.\n\nDURATION can be a decimal fraction. An optional suffix can be \"m\"\n(minutes), \"h\" (hours), \"d\" (days), or \"s\" (seconds, the default).\n\n-i	Only kill for inactivity (restart timeout when command produces output)\n-k	Send KILL signal if child still running this long after first signal\n-s	Send specified signal (default TERM)\n-v	Verbose\n--foreground       Don't create new process group\n--preserve-status  Exit with the child's exit status"
 
 #define HELP_taskset "usage: taskset [-ap] [mask] [PID | cmd [args...]]\n\nLaunch a new task which may only run on certain processors, or change\nthe processor affinity of an existing PID.\n\nMask is a hex string where each bit represents a processor the process\nis allowed to run on. PID without a mask displays existing affinity.\n\n-p	Set/get the affinity of given PID instead of a new command\n-a	Set/get the affinity of all threads of the PID"
 
@@ -174,10 +178,12 @@
 
 #define HELP_swapon "usage: swapon [-d] [-p priority] filename\n\nEnable swapping on a given device/file.\n\n-d	Discard freed SSD pages\n-p	Priority (highest priority areas allocated first)"
 
-#define HELP_swapoff "usage: swapoff swapregion\n\nDisable swapping on a given swapregion."
+#define HELP_swapoff "usage: swapoff FILE\n\nDisable swapping on a device or file."
 
 #define HELP_stat "usage: stat [-tfL] [-c FORMAT] FILE...\n\nDisplay status of files or filesystems.\n\n-c	Output specified FORMAT string instead of default\n-f	Display filesystem status instead of file status\n-L	Follow symlinks\n-t	terse (-c \"%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o\")\n	      (with -f = -c \"%n %i %l %t %s %S %b %f %a %c %d\")\n\nThe valid format escape sequences for files:\n%a  Access bits (octal) |%A  Access bits (flags)|%b  Size/512\n%B  Bytes per %b (512)  |%C  Security context   |%d  Device ID (dec)\n%D  Device ID (hex)     |%f  All mode bits (hex)|%F  File type\n%g  Group ID            |%G  Group name         |%h  Hard links\n%i  Inode               |%m  Mount point        |%n  Filename\n%N  Long filename       |%o  I/O block size     |%s  Size (bytes)\n%t  Devtype major (hex) |%T  Devtype minor (hex)|%u  User ID\n%U  User name           |%x  Access time        |%X  Access unix time\n%y  Modification time   |%Y  Mod unix time      |%z  Creation time\n%Z  Creation unix time\n\nThe valid format escape sequences for filesystems:\n%a  Available blocks    |%b  Total blocks       |%c  Total inodes\n%d  Free inodes         |%f  Free blocks        |%i  File system ID\n%l  Max filename length |%n  File name          |%s  Best transfer size\n%S  Actual block size   |%t  FS type (hex)      |%T  FS type (driver name)"
 
+#define HELP_shuf "usage: shuf [-ze] [-n COUNT] [FILE...]\n\nWrite lines of input to output in random order.\n\n-z	Input/output lines are NUL terminated.\n-n	Stop after COUNT many output lines.\n-e	Echo mode: arguments are inputs to shuffle, not files to read."
+
 #define HELP_shred "usage: shred [-fuxz] [-n COUNT] [-o OFFSET] [-s SIZE] FILE...\n\nSecurely delete a file by overwriting its contents with random data.\n\n-f		Force (chmod if necessary)\n-n COUNT	Random overwrite iterations (default 1)\n-o OFFSET	Start at OFFSET\n-s SIZE		Use SIZE instead of detecting file size\n-u		Unlink (actually delete file when done)\n-x		Use exact size (default without -s rounds up to next 4k)\n-z		Zero at end\n\nNote: data journaling filesystems render this command useless, you must\noverwrite all free space (fill up disk) to erase old data on those."
 
 #define HELP_sha3sum "usage: sha3sum [-S] [-a BITS] [FILE...]\n\nHash function du jour.\n\n-a	Produce a hash BITS long (default 224)\n-b	Brief (hash only, no filename)\n-S	Use SHAKE termination byte instead of SHA3 (ask FIPS why)"
@@ -196,9 +202,9 @@
 
 #define HELP_reboot "usage: reboot/halt/poweroff [-fn] [-d DELAY]\n\nRestart, halt, or power off the system.\n\n-d	Wait DELAY before proceeding (in seconds or m/h/d suffix: -d 1.5m = 90s)\n-f	Force reboot (don't signal init, reboot directly)\n-n	Don't sync filesystems before reboot"
 
-#define HELP_realpath "usage: realpath FILE...\n\nDisplay the canonical absolute pathname"
+#define HELP_realpath "usage: realpath [-LPemqsz] [--relative-base DIR] [-R DIR] FILE...\n\nDisplay the canonical absolute pathname\n\n-R Show ../path relative to DIR (--relative-to)\n-L Logical path (resolve .. before symlinks)\n-P Physical path (default)\n-e Canonical path to existing entry (fail if missing)\n-m Ignore missing entries, show where it would be\n-q Quiet (no error messages)\n-s Don't expand symlinks\n-z NUL instead of newline\n--relative-base  If path under DIR trim off prefix"
 
-#define HELP_readlink "usage: readlink FILE...\n\nWith no options, show what symlink points to, return error if not symlink.\n\nOptions for producing canonical paths (all symlinks/./.. resolved):\n\n-e	Canonical path to existing entry (fail if missing)\n-f	Full path (fail if directory missing)\n-m	Ignore missing entries, show where it would be\n-n	No trailing newline\n-q	Quiet (no output, just error code)"
+#define HELP_readlink "usage: readlink FILE...\n\nWith no options, show what symlink points to, return error if not symlink.\n\nOptions for producing canonical paths (all symlinks/./.. resolved):\n\n-e	Canonical path to existing entry (fail if missing)\n-f	Full path (fail if directory missing)\n-m	Ignore missing entries, show where it would be\n-n	No trailing newline\n-q	Quiet (no error messages)\n-z	NUL instead of newline"
 
 #define HELP_readelf "usage: readelf [-adehlnSs] [-p SECTION] [-x SECTION] [file...]\n\nDisplays information about ELF files.\n\n-a	Equivalent to -dhlnSs\n-d	Show dynamic section\n-e	Headers (equivalent to -hlS)\n-h	Show ELF header\n-l	Show program headers\n-n	Show notes\n-p S	Dump strings found in named/numbered section\n-S	Show section headers\n-s	Show symbol tables (.dynsym and .symtab)\n-x S	Hex dump of named/numbered section\n\n--dyn-syms	Show just .dynsym symbol table"
 
@@ -210,7 +216,7 @@
 
 #define HELP_printenv "usage: printenv [-0] [env_var...]\n\nPrint environment variables.\n\n-0	Use \\0 as delimiter instead of \\n"
 
-#define HELP_pmap "usage: pmap [-pqx] PID...\n\nReport the memory map of a process or processes.\n\n-q	Show full paths\n-q	Do not show header or footer\n-x	Show the extended format"
+#define HELP_pmap "usage: pmap [-pqx] PID...\n\nReport the memory map of a process or processes.\n\n-p	Show full paths\n-q	Do not show header or footer\n-x	Show the extended format"
 
 #define HELP_pivot_root "usage: pivot_root OLD NEW\n\nSwap OLD and NEW filesystems (as if by simultaneous mount --move), and\nmove all processes with chdir or chroot under OLD into NEW (including\nkernel threads) so OLD may be unmounted.\n\nThe directory NEW must exist under OLD. This doesn't work on initramfs,\nwhich can't be moved (about the same way PID 1 can't be killed; see\nswitch_root instead)."
 
@@ -224,11 +230,13 @@
 
 #define HELP_oneit "usage: oneit [-prn3] [-c CONSOLE] [COMMAND...]\n\nSimple init program that runs a single supplied command line with a\ncontrolling tty (so CTRL-C can kill it).\n\n-c	Which console device to use (/dev/console doesn't do CTRL-C, etc)\n-p	Power off instead of rebooting when command exits\n-r	Restart child when it exits\n-n	No reboot, just relaunch command line\n-3	Write 32 bit PID of each exiting reparented process to fd 3 of child\n	(Blocking writes, child must read to avoid eventual deadlock.)\n\nSpawns a single child process (because PID 1 has signals blocked)\nin its own session, reaps zombies until the child exits, then\nreboots the system (or powers off with -p, or restarts the child with -r).\n\nResponds to SIGUSR1 by halting the system, SIGUSR2 by powering off,\nand SIGTERM or SIGINT reboot."
 
-#define HELP_nsenter "usage: nsenter [-t pid] [-F] [-i] [-m] [-n] [-p] [-u] [-U] COMMAND...\n\nRun COMMAND in an existing (set of) namespace(s).\n\n-t	PID to take namespaces from    (--target)\n-F	don't fork, even if -p is used (--no-fork)\n\nThe namespaces to switch are:\n\n-i	SysV IPC: message queues, semaphores, shared memory (--ipc)\n-m	Mount/unmount tree (--mount)\n-n	Network address, sockets, routing, iptables (--net)\n-p	Process IDs and init, will fork unless -F is used (--pid)\n-u	Host and domain names (--uts)\n-U	UIDs, GIDs, capabilities (--user)\n\nIf -t isn't specified, each namespace argument must provide a path\nto a namespace file, ala \"-i=/proc/$PID/ns/ipc\""
+#define HELP_nsenter "usage: nsenter [-t pid] [-F] [-i] [-m] [-n] [-p] [-u] [-U] COMMAND...\n\nRun COMMAND in an existing (set of) namespace(s).\n\n-a	Enter all supported namespaces (--all)\n-F	don't fork, even if -p is used (--no-fork)\n-t	PID to take namespaces from    (--target)\n\nThe namespaces to switch are:\n\n-C	Control groups (--cgroup)\n-i	SysV IPC: message queues, semaphores, shared memory (--ipc)\n-m	Mount/unmount tree (--mount)\n-n	Network address, sockets, routing, iptables (--net)\n-p	Process IDs and init, will fork unless -F is used (--pid)\n-u	Host and domain names (--uts)\n-U	UIDs, GIDs, capabilities (--user)\n\nIf -t isn't specified, each namespace argument must provide a path\nto a namespace file, ala \"-i=/proc/$PID/ns/ipc\""
 
-#define HELP_unshare "usage: unshare [-imnpuUr] COMMAND...\n\nCreate new container namespace(s) for this process and its children, so\nsome attribute is not shared with the parent process.\n\n-f	Fork command in the background (--fork)\n-i	SysV IPC (message queues, semaphores, shared memory) (--ipc)\n-m	Mount/unmount tree (--mount)\n-n	Network address, sockets, routing, iptables (--net)\n-p	Process IDs and init (--pid)\n-r	Become root (map current euid/egid to 0/0, implies -U) (--map-root-user)\n-u	Host and domain names (--uts)\n-U	UIDs, GIDs, capabilities (--user)\n\nA namespace allows a set of processes to have a different view of the\nsystem than other sets of processes."
+#define HELP_unshare "usage: unshare [-imnpuUr] COMMAND...\n\nCreate new container namespace(s) for this process and its children, allowing\nthe new set of processes to have a different view of the system than the\nparent process.\n\n-a	Unshare all supported namespaces\n-f	Fork command in the background (--fork)\n-r	Become root (map current euid/egid to 0/0, implies -U) (--map-root-user)\n\nAvailable namespaces:\n-C	Control groups (--cgroup)\n-i	SysV IPC (message queues, semaphores, shared memory) (--ipc)\n-m	Mount/unmount tree (--mount)\n-n	Network address, sockets, routing, iptables (--net)\n-p	Process IDs and init (--pid)\n-u	Host and domain names (--uts)\n-U	UIDs, GIDs, capabilities (--user)\n\nEach namespace can take an optional argument, a persistent mountpoint usable\nby the nsenter command to add new processes to that the namespace. (Specify\nmultiple namespaces to unshare separately, ala -c -i -m because -cim is -c\nwith persistent mount \"im\".)"
 
-#define HELP_nbd_client "usage: nbd-client [-ns] HOST PORT DEVICE\n\n-n	Do not fork into background\n-s	nbd swap support (lock server into memory)"
+#define HELP_nbd_server "usage: nbd-server [-r] FILE\n\nServe a Network Block Device from FILE on stdin/out (ala inetd).\n\n-r	Read only export"
+
+#define HELP_nbd_client "usage: nbd-client [-ns] [-b BLKSZ] HOST PORT DEVICE\n\n-b	Block size (default 4096)\n-n	Do not daemonize\n-s	nbd swap support (lock server into memory)"
 
 #define HELP_mountpoint "usage: mountpoint [-qd] DIR\n       mountpoint [-qx] DEVICE\n\nCheck whether the directory or device is a mountpoint.\n\n-q	Be quiet, return zero if directory is a mountpoint\n-d	Print major/minor device number of the directory\n-x	Print major/minor device number of the block device"
 
@@ -246,7 +254,7 @@
 
 #define HELP_lsusb "usage: lsusb [-i]\n\nList USB hosts/devices.\n\n-i	ID database (default /etc/usb.ids[.gz])"
 
-#define HELP_lspci "usage: lspci [-ekmn] [-i FILE]\n\nList PCI devices.\n\n-e  Extended (6 digit) class\n-i  ID database (default /etc/pci.ids[.gz])\n-k  Show kernel driver\n-m  Machine readable\n-n  Numeric output (-nn for both)"
+#define HELP_lspci "usage: lspci [-ekmn] [-i FILE]\n\nList PCI devices.\n\n-e	Extended (6 digit) class\n-i	ID database (default /etc/pci.ids[.gz])\n-k	Show kernel driver\n-m	Machine readable\n-n	Numeric output (-nn for both)\n-x	Hex dump of config space (64 bytes; -xxx for 256, -xxxx for 4096)"
 
 #define HELP_lsmod "usage: lsmod\n\nDisplay the currently loaded modules, their sizes and their dependencies."
 
@@ -266,13 +274,13 @@
 
 #define HELP_inotifyd "usage: inotifyd PROG FILE[:MASK] ...\n\nWhen a filesystem event matching MASK occurs to a FILE, run PROG as:\n\n  PROG EVENTS FILE [DIRFILE]\n\nIf PROG is \"-\" events are sent to stdout.\n\nThis file is:\n  a  accessed    c  modified    e  metadata change  w  closed (writable)\n  r  opened      D  deleted     M  moved            0  closed (unwritable)\n  u  unmounted   o  overflow    x  unwatchable\n\nA file in this directory is:\n  m  moved in    y  moved out   n  created          d  deleted\n\nWhen x event happens for all FILEs, inotifyd exits (after waiting for PROG)."
 
-#define HELP_i2cset "usage: i2cset [-fy] BUS CHIP ADDR VALUE... MODE\n\nWrite an i2c register. MODE is b for byte, w for 16-bit word, i for I2C block.\n\n-f	Force access to busy devices\n-y	Answer \"yes\" to confirmation prompts (for script use)"
+#define HELP_i2cset "usage: i2cset [-fy] BUS CHIP ADDR VALUE... MODE\n\nWrite an i2c register. MODE is b for byte, w for 16-bit word, i for I2C block.\n\n-f	Force access to busy devices\n-y	Skip confirmation prompts (yes to all)"
 
-#define HELP_i2cget "usage: i2cget [-fy] BUS CHIP ADDR\n\nRead an i2c register.\n\n-f	Force access to busy devices\n-y	Answer \"yes\" to confirmation prompts (for script use)"
+#define HELP_i2cget "usage: i2cget [-fy] BUS CHIP [ADDR]\n\nRead an i2c register.\n\n-f	Force access to busy devices\n-y	Skip confirmation prompts (yes to all)"
 
-#define HELP_i2cdump "usage: i2cdump [-fy] BUS CHIP\n\nDump i2c registers.\n\n-f	Force access to busy devices\n-y	Answer \"yes\" to confirmation prompts (for script use)"
+#define HELP_i2cdump "usage: i2cdump [-fy] BUS CHIP\n\nDump i2c registers.\n\n-f	Force access to busy devices\n-y	Skip confirmation prompts (yes to all)"
 
-#define HELP_i2cdetect "usage: i2cdetect [-aqry] BUS [FIRST LAST]\nusage: i2cdetect -F BUS\nusage: i2cdetect -l\n\nDetect i2c devices.\n\n-a	All addresses (0x00-0x7f rather than 0x03-0x77 or FIRST-LAST)\n-F	Show functionality\n-l	List available buses\n-q	Probe with SMBus Quick Write (default)\n-r	Probe with SMBus Read Byte\n-y	Answer \"yes\" to confirmation prompts (for script use)"
+#define HELP_i2cdetect "usage: i2cdetect [-aqry] BUS [FIRST LAST]\nusage: i2cdetect -F BUS\nusage: i2cdetect -l\n\nDetect i2c devices.\n\n-a	All addresses (0x00-0x7f rather than 0x03-0x77 or FIRST-LAST)\n-F	Show functionality\n-l	List available buses\n-q	Probe with SMBus Quick Write (default)\n-r	Probe with SMBus Read Byte\n-y	Skip confirmation prompts (yes to all)"
 
 #define HELP_hwclock "usage: hwclock [-rswtluf]\n\nGet/set the hardware clock.\n\n-f FILE	Use specified device file instead of /dev/rtc0 (--rtc)\n-l	Hardware clock uses localtime (--localtime)\n-r	Show hardware clock time (--show)\n-s	Set system time from hardware clock (--hctosys)\n-t	Set the system time based on the current timezone (--systz)\n-u	Hardware clock uses UTC (--utc)\n-w	Set hardware clock from system time (--systohc)"
 
@@ -304,7 +312,7 @@
 
 #define HELP_fallocate "usage: fallocate [-l size] [-o offset] file\n\nTell the filesystem to allocate space for a file."
 
-#define HELP_factor "usage: factor NUMBER...\n\nFactor integers."
+#define HELP_factor "usage: factor NUMBER...\n\nFactor integers.\n\n-h	Human readable: show repeated factors as x^n\n-x	Hexadecimal output"
 
 #define HELP_eject "usage: eject [-stT] [DEVICE]\n\nEject DEVICE or default /dev/cdrom\n\n-s	SCSI device\n-t	Close tray\n-T	Open/close tray (toggle)"
 
@@ -332,7 +340,7 @@
 
 #define HELP_fstype "usage: fstype DEV...\n\nPrint type of filesystem on a block device or image."
 
-#define HELP_blkid "usage: blkid [-s TAG] [-UL] DEV...\n\nPrint type, label and UUID of filesystem on a block device or image.\n\n-U	Show UUID only (or device with that UUID)\n-L	Show LABEL only (or device with that LABEL)\n-s TAG	Only show matching tags (default all)"
+#define HELP_blkid "usage: blkid [-o TYPE] [-s TAG] [-UL] DEV...\n\nPrint type, label and UUID of filesystem on a block device or image.\n\n-U	Show UUID only (or device with that UUID)\n-L	Show LABEL only (or device with that LABEL)\n-o TYPE	Output format (full, value, export)\n-s TAG	Only show matching tags (default all)"
 
 #define HELP_blkdiscard "usage: blkdiscard [-olszf] DEVICE\n\nDiscard device sectors.\n\n-o, --offset OFF	Byte offset to start discarding at (default 0)\n-l, --length LEN	Bytes to discard (default all)\n-s, --secure		Perform secure discard\n-z, --zeroout		Zero-fill rather than discard\n-f, --force		Disable check for mounted filesystem\n\nOFF and LEN must be aligned to the device sector size.\nBy default entire device is discarded.\nWARNING: All discarded data is permanently lost!"
 
@@ -348,13 +356,7 @@
 
 #define HELP_xzcat "usage: xzcat [filename...]\n\nDecompress listed files to stdout. Use stdin if no files listed."
 
-#define HELP_wget_openssl "Enable HTTPS support for wget by linking to OpenSSL."
-
-#define HELP_wget_libtls "Enable HTTPS support for wget by linking to LibTLS.\nSupports using libtls, libretls or libtls-bearssl."
-
-#define HELP_wget "usage: wget [OPTIONS]... [URL]\n    --max-redirect          maximum redirections allowed\n-d, --debug                 print lots of debugging information\n-O, --output-document=FILE  specify output filename\n-p, --post-data=DATA        send data in body of POST request\n\nexamples:\n  wget http://www.example.com"
-
-#define HELP_vi "usage: vi [-s script] FILE\n-s script: run script file\nVisual text editor. Predates the existence of standardized cursor keys,\nso the controls are weird and historical."
+#define HELP_vi "usage: vi [-s script] FILE\n\nVisual text editor. Predates the existence of standardized cursor keys,\nso the controls are weird and historical.\n\n-s script: run script file"
 
 #define HELP_userdel "usage: userdel [-r] USER\nusage: deluser [-r] USER\n\nDelete USER from the SYSTEM\n\n-r	remove home directory"
 
@@ -408,7 +410,7 @@
 
 #define HELP_cd "usage: cd [-PL] [-] [path]\n\nChange current directory. With no arguments, go $HOME. Sets $OLDPWD to\nprevious directory: cd - to return to $OLDPWD.\n\n-P	Physical path: resolve symlinks in path\n-L	Local path: .. trims directories off $PWD (default)"
 
-#define HELP_sh "usage: sh [-c command] [script]\n\nCommand shell.  Runs a shell script, or reads input interactively\nand responds to it.\n\n-c	command line to execute\n-i	interactive mode (default when STDIN is a tty)"
+#define HELP_sh "usage: sh [-c command] [script]\n\nCommand shell.  Runs a shell script, or reads input interactively\nand responds to it. Roughly compatible with \"bash\". Run \"help\" for\nlist of built-in commands.\n\n-c	command line to execute\n-i	interactive mode (default when STDIN is a tty)\n-s	don't run script (args set $* parameters but read commands from stdin)\n\nCommand shells parse each line of input (prompting when interactive), perform\nvariable expansion and redirection, execute commands (spawning child processes\nand background jobs), and perform flow control based on the return code.\n\nParsing:\n  syntax errors\n\nInteractive prompts:\n  line continuation\n\nVariable expansion:\n  Note: can cause syntax errors at runtime\n\nRedirection:\n  HERE documents (parsing)\n  Pipelines (flow control and job control)\n\nRunning commands:\n  process state\n  builtins\n    cd [[ ]] (( ))\n    ! : [ # TODO: help for these?\n    true false help echo kill printf pwd test\n  child processes\n\nJob control:\n  &    Background process\n  Ctrl-C kill process\n  Ctrl-Z suspend process\n  bg fg jobs kill\n\nFlow control:\n;    End statement (same as newline)\n&    Background process (returns true unless syntax error)\n&&   If this fails, next command fails without running\n||   If this succeeds, next command succeeds without running\n|    Pipelines! (Can of worms...)\nfor {name [in...]}|((;;)) do; BODY; done\nif TEST; then BODY; fi\nwhile TEST; do BODY; done\ncase a in X);; esac\n[[ TEST ]]\n((MATH))\n\nJob control:\n&    Background process\nCtrl-C kill process\nCtrl-Z suspend process\nbg fg jobs kill"
 
 #define HELP_route "usage: route [-ne] [-A [inet|inet6]] [add|del TARGET [OPTIONS]]\n\nDisplay, add or delete network routes in the \"Forwarding Information Base\",\nwhich send packets out a network interface to an address.\n\n-n	Show numerical addresses (no DNS lookups)\n-e	display netstat fields\n\nAssigning an address to an interface automatically creates an appropriate\nnetwork route (\"ifconfig eth0 10.0.2.15/8\" does \"route add 10.0.0.0/8 eth0\"\nfor you), although some devices (such as loopback) won't show it in the\ntable. For machines more than one hop away, you need to specify a gateway\n(ala \"route add default gw 10.0.2.2\").\n\nThe address \"default\" is a wildcard address (0.0.0.0/0) matching all\npackets without a more specific route.\n\nAvailable OPTIONS include:\nreject   - blocking route (force match failure)\ndev NAME - force matching packets out this interface (ala \"eth0\")\nnetmask  - old way of saying things like ADDR/24\ngw ADDR  - forward packets to gateway ADDR"
 
@@ -454,6 +456,18 @@
 
 #define HELP_groupadd "usage: groupadd [-S] [-g GID] [USER] GROUP\n\nAdd a group or add a user to a group\n\n  -g GID Group id\n  -S     Create a system group"
 
+#define HELP_gitcheckout "usage: gitcheckout <branch>\nA minimal git checkout."
+
+#define HELP_gitfetch "usage: gitfetch\nA minimal git fetch."
+
+#define HELP_gitremote "usage: gitremote URL\nA minimal git remote add origin."
+
+#define HELP_gitinit "usage: gitinit NAME\nA minimal git init."
+
+#define HELP_gitclone "usage: gitclone URL\nA minimal git clone."
+
+#define HELP_gitcompat "Enable git compatible repos instead of minimal clone downloader."
+
 #define HELP_getty "usage: getty [OPTIONS] BAUD_RATE[,BAUD_RATE]... TTY [TERMTYPE]\n\nWait for a modem to dial into serial port, adjust baud rate, call login.\n\n-h    Enable hardware RTS/CTS flow control\n-L    Set CLOCAL (ignore Carrier Detect state)\n-m    Get baud rate from modem's CONNECT status message\n-n    Don't prompt for login name\n-w    Wait for CR or LF before sending /etc/issue\n-i    Don't display /etc/issue\n-f ISSUE_FILE  Display ISSUE_FILE instead of /etc/issue\n-l LOGIN  Invoke LOGIN instead of /bin/login\n-t SEC    Terminate after SEC if no login name is read\n-I INITSTR  Send INITSTR before anything else\n-H HOST    Log HOST into the utmp file as the hostname"
 
 #define HELP_getopt "usage: getopt [OPTIONS] [--] ARG...\n\nParse command-line options for use in shell scripts.\n\n-a	Allow long options starting with a single -.\n-l OPTS	Specify long options.\n-n NAME	Command name for error messages.\n-o OPTS	Specify short options.\n-T	Test whether this is a modern getopt.\n-u	Output options unquoted."
@@ -470,7 +484,7 @@
 
 #define HELP_dumpleases "usage: dumpleases [-r|-a] [-f LEASEFILE]\n\nDisplay DHCP leases granted by udhcpd\n-f FILE,  Lease file\n-r        Show remaining time\n-a        Show expiration time"
 
-#define HELP_diff "usage: diff [-abBdiNqrTstw] [-L LABEL] [-S FILE] [-U LINES] FILE1 FILE2\n\n-a	Treat all files as text\n-b	Ignore changes in the amount of whitespace\n-B	Ignore changes whose lines are all blank\n-d	Try hard to find a smaller set of changes\n-i	Ignore case differences\n-L	Use LABEL instead of the filename in the unified header\n-N	Treat absent files as empty\n-q	Output only whether files differ\n-r	Recurse\n-S	Start with FILE when comparing directories\n-T	Make tabs line up by prefixing a tab when necessary\n-s	Report when two files are the same\n-t	Expand tabs to spaces in output\n-u	Unified diff\n-U	Output LINES lines of context\n-w	Ignore all whitespace\n\n--color              Colored output\n--strip-trailing-cr  Strip trailing '\\r's from input lines"
+#define HELP_diff "usage: diff [-abBdiNqrTstw] [-L LABEL] [-S FILE] [-U LINES] [-F REGEX ] FILE1 FILE2\n\n-a	Treat all files as text\n-b	Ignore changes in the amount of whitespace\n-B	Ignore changes whose lines are all blank\n-d	Try hard to find a smaller set of changes\n-F 	Show the most recent line matching the regex\n-i	Ignore case differences\n-L	Use LABEL instead of the filename in the unified header\n-N	Treat absent files as empty\n-q	Output only whether files differ\n-r	Recurse\n-S	Start with FILE when comparing directories\n-s	Report when two files are the same\n-T	Make tabs line up by prefixing a tab when necessary\n-t	Expand tabs to spaces in output\n-u	Unified diff\n-U	Output LINES lines of context\n-w	Ignore all whitespace\n\n--color     Color output   --strip-trailing-cr   Strip '\\r' from input lines\n--TYPE-line-format=FORMAT  Display TYPE (unchanged/old/new) lines using FORMAT\n  FORMAT uses printf integer escapes (ala %-2.4x) followed by LETTER: FELMNn\nSupported format specifiers are:\n* %l, the contents of the line, without the trailing newline\n* %L, the contents of the line, including the trailing newline\n* %%, the character '%'"
 
 #define HELP_dhcpd "usage: dhcpd [-46fS] [-i IFACE] [-P N] [CONFFILE]\n\n -f    Run in foreground\n -i Interface to use\n -S    Log to syslog too\n -P N  Use port N (default ipv4 67, ipv6 547)\n -4, -6    Run as a DHCPv4 or DHCPv6 server"
 
@@ -478,7 +492,7 @@
 
 #define HELP_dhcp "usage: dhcp [-fbnqvoCRB] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n            [-H HOSTNAME] [-V VENDOR] [-x OPT:VAL] [-O OPT]\n\n     Configure network dynamically using DHCP.\n\n   -i Interface to use (default eth0)\n   -p Create pidfile\n   -s Run PROG at DHCP events (default /usr/share/dhcp/default.script)\n   -B Request broadcast replies\n   -t Send up to N discover packets\n   -T Pause between packets (default 3 seconds)\n   -A Wait N seconds after failure (default 20)\n   -f Run in foreground\n   -b Background if lease is not obtained\n   -n Exit if lease is not obtained\n   -q Exit after obtaining lease\n   -R Release IP on exit\n   -S Log to syslog too\n   -a Use arping to validate offered address\n   -O Request option OPT from server (cumulative)\n   -o Don't request any options (unless -O is given)\n   -r Request this IP address\n   -x OPT:VAL  Include option OPT in sent packets (cumulative)\n   -F Ask server to update DNS mapping for NAME\n   -H Send NAME as client hostname (default none)\n   -V VENDOR Vendor identifier (default 'toybox VERSION')\n   -C Don't send MAC as client identifier\n   -v Verbose\n\n   Signals:\n   USR1  Renew current lease\n   USR2  Release current lease"
 
-#define HELP_dd "usage: dd [if=FILE] [of=FILE] [ibs=N] [obs=N] [iflag=FLAGS] [oflag=FLAGS]\n        [bs=N] [count=N] [seek=N] [skip=N]\n        [conv=notrunc|noerror|sync|fsync] [status=noxfer|none]\n\nCopy/convert files.\n\nif=FILE		Read from FILE instead of stdin\nof=FILE		Write to FILE instead of stdout\nbs=N		Read and write N bytes at a time\nibs=N		Input block size\nobs=N		Output block size\ncount=N		Copy only N input blocks\nskip=N		Skip N input blocks\nseek=N		Skip N output blocks\niflag=FLAGS	Set input flags\noflag=FLAGS	Set output flags\nconv=notrunc	Don't truncate output file\nconv=noerror	Continue after read errors\nconv=sync	Pad blocks with zeros\nconv=fsync	Physically write data out before finishing\nstatus=noxfer	Don't show transfer rate\nstatus=none	Don't show transfer rate or records in/out\n\nFLAGS is a comma-separated list of:\n\ncount_bytes	(iflag) interpret count=N in bytes, not blocks\nseek_bytes	(oflag) interpret seek=N in bytes, not blocks\nskip_bytes	(iflag) interpret skip=N in bytes, not blocks\n\nNumbers may be suffixed by c (*1), w (*2), b (*512), kD (*1000), k (*1024),\nMD (*1000*1000), M (*1024*1024), GD (*1000*1000*1000) or G (*1024*1024*1024)."
+#define HELP_dd "usage: dd [if|of=FILE] [ibs|obs|bs|count|seek|skip=N] [conv|status|iflag|oflag=FLAG[,FLAG...]]\n\nCopy/convert blocks of data from input to output, with the following\nkeyword=value modifiers (and their default values):\n\nif=FILE  Read FILE (stdin)          of=FILE  Write to FILE (stdout)\n   bs=N  Block size in bytes (512)  count=N  Stop after copying N blocks\n  ibs=N  Input block size (bs=)       obs=N  Output block size (bs=)\n skip=N  Skip N input blocks (0)     seek=N  Skip N output blocks (0)\n\nEach =N value accepts the normal unit suffixes (see toybox --help).\n\nThese modifiers take a comma separated list of potential options:\n\niflag=count_bytes,skip_bytes   count=N or skip=N is in bytes not blocks\noflag=seek_bytes,append        seek=N is in bytes, append output to file\nstatus=noxfer,none             don't show transfer rate, no summary info\nconv=\n  notrunc  Don't truncate output    noerror  Continue after read errors\n  sync     Zero pad short reads     fsync    Flush output to disk at end\n  sparse   Seek past zeroed output  excl     Fail if output file exists\n  nocreat  Fail if of=FILE missing"
 
 #define HELP_crontab "usage: crontab [-u user] FILE\n               [-u user] [-e | -l | -r]\n               [-c dir]\n\nFiles used to schedule the execution of programs.\n\n-c crontab dir\n-e edit user's crontab\n-l list user's crontab\n-r delete user's crontab\n-u user\nFILE Replace crontab by FILE ('-': stdin)"
 
@@ -488,7 +502,7 @@
 
 #define HELP_brctl "usage: brctl COMMAND [BRIDGE [INTERFACE]]\n\nManage ethernet bridges\n\nCommands:\nshow                  Show a list of bridges\naddbr BRIDGE          Create BRIDGE\ndelbr BRIDGE          Delete BRIDGE\naddif BRIDGE IFACE    Add IFACE to BRIDGE\ndelif BRIDGE IFACE    Delete IFACE from BRIDGE\nsetageing BRIDGE TIME Set ageing time\nsetfd BRIDGE TIME     Set bridge forward delay\nsethello BRIDGE TIME  Set hello time\nsetmaxage BRIDGE TIME Set max message age\nsetpathcost BRIDGE PORT COST   Set path cost\nsetportprio BRIDGE PORT PRIO   Set port priority\nsetbridgeprio BRIDGE PRIO      Set bridge priority\nstp BRIDGE [1/yes/on|0/no/off] STP on/off"
 
-#define HELP_bootchartd "usage: bootchartd {start [PROG ARGS]}|stop|init\n\nCreate /var/log/bootlog.tgz with boot chart data\n\nstart: start background logging; with PROG, run PROG,\n       then kill logging with USR1\nstop:  send USR1 to all bootchartd processes\ninit:  start background logging; stop when getty/xdm is seen\n      (for init scripts)\n\nUnder PID 1: as init, then exec $bootchart_init, /init, /sbin/init"
+#define HELP_bootchartd "usage: bootchartd {start [PROG ARGS]}|stop|init\n\nRecord boot chart data into /var/log/bootlog.tgz\n\nstart: start background logging; with PROG, run PROG,\n       then kill logging with SIGUSR1\nstop:  send SIGUSR1 to all bootchartd processes\ninit:  start background logging; stop when getty/xdm is seen\n      (for init scripts)\n\nUnder PID 1: as init, then exec $bootchart_init, /init, /sbin/init"
 
 #define HELP_bc "usage: bc [-ilqsw] [file ...]\n\nbc is a command-line calculator with a Turing-complete language.\n\noptions:\n\n  -i  --interactive  force interactive mode\n  -l  --mathlib      use predefined math routines:\n\n                     s(expr)  =  sine of expr in radians\n                     c(expr)  =  cosine of expr in radians\n                     a(expr)  =  arctangent of expr, returning radians\n                     l(expr)  =  natural log of expr\n                     e(expr)  =  raises e to the power of expr\n                     j(n, x)  =  Bessel function of integer order n of x\n\n  -q  --quiet        don't print version and copyright\n  -s  --standard     error if any non-POSIX extensions are used\n  -w  --warn         warn if any non-POSIX extensions are used"
 
@@ -526,11 +540,11 @@
 
 #define HELP_time "usage: time [-pv] COMMAND...\n\nRun command line and report real, user, and system time elapsed in seconds.\n(real = clock on the wall, user = cpu used by command's code,\nsystem = cpu used by OS on behalf of command.)\n\n-p	POSIX format output\n-v	Verbose"
 
-#define HELP_test "usage: test [-bcdefghLPrSsuwx PATH] [-nz STRING] [-t FD] [X ?? Y]\n\nReturn true or false by performing tests. (With no arguments return false.)\n\n--- Tests with a single argument (after the option):\nPATH is/has:\n  -b  block device   -f  regular file   -p  fifo           -u  setuid bit\n  -c  char device    -g  setgid         -r  read bit       -w  write bit\n  -d  directory      -h  symlink        -S  socket         -x  execute bit\n  -e  exists         -L  symlink        -s  nonzero size   -k  sticky bit\nSTRING is:\n  -n  nonzero size   -z  zero size      (STRING by itself implies -n)\nFD (integer file descriptor) is:\n  -t  a TTY\n\n--- Tests with one argument on each side of an operator:\nTwo strings:\n  =  are identical   !=  differ\n\nTwo integers:\n  -eq  equal         -gt  first > second    -lt  first < second\n  -ne  not equal     -ge  first >= second   -le  first <= second\n\n--- Modify or combine tests:\n  ! EXPR     not (swap true/false)   EXPR -a EXPR    and (are both true)\n  ( EXPR )   evaluate this first     EXPR -o EXPR    or (is either true)"
+#define HELP_test "usage: test [-bcdefghLPrSsuwx PATH] [-nz STRING] [-t FD] [X ?? Y]\n\nReturn true or false by performing tests. No arguments is false, one argument\nis true if not empty string.\n\n--- Tests with a single argument (after the option):\nPATH is/has:\n  -b  block device   -f  regular file   -p  fifo           -u  setuid bit\n  -c  char device    -g  setgid         -r  readable       -w  writable\n  -d  directory      -h  symlink        -S  socket         -x  executable\n  -e  exists         -L  symlink        -s  nonzero size   -k  sticky bit\nSTRING is:\n  -n  nonzero size   -z  zero size\nFD (integer file descriptor) is:\n  -t  a TTY          -T  open\n\n--- Tests with one argument on each side of an operator:\nTwo strings:\n  =  are identical   !=  differ         =~  string matches regex\nAlphabetical sort:\n  <  first is lower  >   first higher\nTwo integers:\n  -eq  equal         -gt  first > second    -lt  first < second\n  -ne  not equal     -ge  first >= second   -le  first <= second\n\n--- Modify or combine tests:\n  ! EXPR     not (swap true/false)   EXPR -a EXPR    and (are both true)\n  ( EXPR )   evaluate this first     EXPR -o EXPR    or (is either true)"
 
 #define HELP_tee "usage: tee [-ai] [FILE...]\n\nCopy stdin to each listed file, and also to stdout.\nFilename \"-\" is a synonym for stdout.\n\n-a	Append to files\n-i	Ignore SIGINT"
 
-#define HELP_tar "usage: tar [-cxt] [-fvohmjkOS] [-XTCf NAME] [--selinux] [FILE...]\n\nCreate, extract, or list files in a .tar (or compressed t?z) file.\n\nOptions:\nc  Create                x  Extract               t  Test (list)\nf  tar FILE (default -)  C  Change to DIR first   v  Verbose display\no  Ignore owner          h  Follow symlinks       m  Ignore mtime\nJ  xz compression        j  bzip2 compression     z  gzip compression\nO  Extract to stdout     X  exclude names in FILE T  include names in FILE\n\n--exclude        FILENAME to exclude  --full-time         Show seconds with -tv\n--mode MODE      Adjust permissions   --owner NAME[:UID]  Set file ownership\n--mtime TIME     Override timestamps  --group NAME[:GID]  Set file group\n--sparse         Record sparse files  --selinux           Save/restore labels\n--restrict       All under one dir    --no-recursion      Skip dir contents\n--numeric-owner  Use numeric uid/gid, not user/group names\n--strip-components NUM  Ignore first NUM directory components when extracting\n-I PROG          Filter through PROG to compress or PROG -d to decompress"
+#define HELP_tar "usage: tar [-cxt] [-fvohmjkOS] [-XTCf NAME] [--selinux] [FILE...]\n\nCreate, extract, or list files in a .tar (or compressed t?z) file.\n\nOptions:\nc  Create                x  Extract               t  Test (list)\nf  tar FILE (default -)  C  Change to DIR first   v  Verbose display\nJ  xz compression        j  bzip2 compression     z  gzip compression\no  Ignore owner          h  Follow symlinks       m  Ignore mtime\nO  Extract to stdout     X  exclude names in FILE T  include names in FILE\ns  Sort dirs (--sort)\n\n--exclude        FILENAME to exclude  --full-time         Show seconds with -tv\n--mode MODE      Adjust permissions   --owner NAME[:UID]  Set file ownership\n--mtime TIME     Override timestamps  --group NAME[:GID]  Set file group\n--sparse         Record sparse files  --selinux           Save/restore labels\n--restrict       All under one dir    --no-recursion      Skip dir contents\n--numeric-owner  Use numeric uid/gid, not user/group names\n--null           Filenames in -T FILE are null-separated, not newline\n--strip-components NUM  Ignore first NUM directory components when extracting\n--xform=SED      Modify filenames via SED expression (ala s/find/replace/g)\n-I PROG          Filter through PROG to compress or PROG -d to decompress\n\nFilename filter types. Create command line args aren't filtered, extract\ndefaults to --anchored, --exclude defaults to --wildcards-match-slash,\nuse no- prefix to disable:\n\n--anchored  Match name not path       --ignore-case       Case insensitive\n--wildcards Expand *?[] like shell    --wildcards-match-slash"
 
 #define HELP_tail "usage: tail [-n|c NUMBER] [-f|F] [-s SECONDS] [FILE...]\n\nCopy last lines from files to stdout. If no files listed, copy from\nstdin. Filename \"-\" is a synonym for stdin.\n\n-n	Output the last NUMBER lines (default 10), +X counts from start\n-c	Output the last NUMBER bytes, +NUMBER counts from start\n-f	Follow FILE(s) by descriptor, waiting for more data to be appended\n-F	Follow FILE(s) by filename, waiting for more data, and retrying\n-s	Used with -F, sleep SECONDS between retries (default 1)"
 
@@ -538,11 +552,11 @@
 
 #define HELP_split "usage: split [-a SUFFIX_LEN] [-b BYTES] [-l LINES] [-n PARTS] [INPUT [OUTPUT]]\n\nCopy INPUT (or stdin) data to a series of OUTPUT (or \"x\") files with\nalphabetically increasing suffix (aa, ab, ac... az, ba, bb...).\n\n-a	Suffix length (default 2)\n-b	BYTES/file (10, 10k, 10m, 10g...)\n-l	LINES/file (default 1000)\n-n	PARTS many equal length files"
 
-#define HELP_sort "usage: sort [-Mbcdfginrsuz] [FILE...] [-k#[,#[x]] [-t X]] [-o FILE]\n\nSort all lines of text from input files (or stdin) to stdout.\n-M	Month sort (jan, feb, etc)\n-V	Version numbers (name-1.234-rc6.5b.tgz)\n-b	Ignore leading blanks (or trailing blanks in second part of key)\n-c	Check whether input is sorted\n-d	Dictionary order (use alphanumeric and whitespace chars only)\n-f	Force uppercase (case insensitive sort)\n-g	General numeric sort (double precision with nan and inf)\n-i	Ignore nonprinting characters\n-k	Sort by \"key\" (see below)\n-n	Numeric order (instead of alphabetical)\n-o	Output to FILE instead of stdout\n-r	Reverse\n-s	Skip fallback sort (only sort with keys)\n-t	Use a key separator other than whitespace\n-u	Unique lines only\n-x	Hexadecimal numerical sort\n-z	Zero (null) terminated lines\n\nSorting by key looks at a subset of the words on each line. -k2 uses the\nsecond word to the end of the line, -k2,2 looks at only the second word,\n-k2,4 looks from the start of the second to the end of the fourth word.\n-k2.4,5 starts from the fourth character of the second word, to the end\nof the fifth word. Specifying multiple keys uses the later keys as tie\nbreakers, in order. A type specifier appended to a sort key (such as -2,2n)\napplies only to sorting that key."
+#define HELP_sort "usage: sort [-Mbcdfginrsuz] [FILE...] [-k#[,#[x]] [-t X]] [-o FILE]\n\nSort all lines of text from input files (or stdin) to stdout.\n-C	Check whether input is sorted\n-M	Month sort (jan, feb, etc)\n-V	Version numbers (name-1.234-rc6.5b.tgz)\n-b	Ignore leading blanks (or trailing blanks in second part of key)\n-c	Warn if input is unsorted\n-d	Dictionary order (use alphanumeric and whitespace chars only)\n-f	Force uppercase (case insensitive sort)\n-g	General numeric sort (double precision with nan and inf)\n-i	Ignore nonprinting characters\n-k	Sort by \"key\" (see below)\n-n	Numeric order (instead of alphabetical)\n-o	Output to FILE instead of stdout\n-r	Reverse\n-s	Skip fallback sort (only sort with keys)\n-t	Use a key separator other than whitespace\n-u	Unique lines only\n-x	Hexadecimal numerical sort\n-z	Zero (null) terminated lines\n\nSorting by key looks at a subset of the words on each line. -k2 uses the\nsecond word to the end of the line, -k2,2 looks at only the second word,\n-k2,4 looks from the start of the second to the end of the fourth word.\n-k2.4,5 starts from the fourth character of the second word, to the end\nof the fifth word. Specifying multiple keys uses the later keys as tie\nbreakers, in order. A type specifier appended to a sort key (such as -2,2n)\napplies only to sorting that key."
 
-#define HELP_sleep "usage: sleep DURATION\n\nWait before exiting.\n\nDURATION can be a decimal fraction. An optional suffix can be \"m\"\n(minutes), \"h\" (hours), \"d\" (days), or \"s\" (seconds, the default)."
+#define HELP_sleep "usage: sleep DURATION...\n\nWait before exiting.\n\nDURATION can be a decimal fraction. An optional suffix can be \"m\"\n(minutes), \"h\" (hours), \"d\" (days), or \"s\" (seconds, the default)."
 
-#define HELP_sed "usage: sed [-inrszE] [-e SCRIPT]...|SCRIPT [-f SCRIPT_FILE]... [FILE...]\n\nStream editor. Apply editing SCRIPTs to lines of input.\n\n-e	Add SCRIPT to list\n-f	Add contents of SCRIPT_FILE to list\n-i	Edit each file in place (-iEXT keeps backup file with extension EXT)\n-n	No default output (use the p command to output matched lines)\n-r	Use extended regular expression syntax\n-E	POSIX alias for -r\n-s	Treat input files separately (implied by -i)\n-z	Use \\0 rather than \\n as input line separator\n\nA SCRIPT is one or more COMMANDs separated by newlines or semicolons.\nAll -e SCRIPTs are combined as if separated by newlines, followed by all -f\nSCRIPT_FILEs. If no -e or -f then first argument is the SCRIPT.\n\nCOMMANDs apply to every line unless prefixed with an ADDRESS of the form:\n\n  [ADDRESS[,ADDRESS]][!]COMMAND\n\nADDRESS is a line number (starting at 1), a /REGULAR EXPRESSION/, or $ for\nlast line (-s or -i makes it last line of each file). One address matches one\nline, ADDRESS,ADDRESS matches from first to second inclusive. Two regexes can\nmatch multiple ranges. ADDRESS,+N ends N lines later. ! inverts the match.\n\nREGULAR EXPRESSIONS start and end with the same character (anything but\nbackslash or newline). To use the delimiter in the regex escape it with a\nbackslash, and printf escapes (\\abcefnrtv and octal, hex, and unicode) work.\nAn empty regex repeats the previous one. ADDRESS regexes require any\nfirst delimiter except / to be \\escaped to distinguish it from COMMANDs.\n\nSed reads each line of input, processes it, and writes it out or discards it\nbefore reading the next. Sed can remember one additional line in a separate\nbuffer (the h, H, g, G, and x commands), and can read the next line of input\nearly (the n and N commands), but otherwise operates on individual lines.\n\nEach COMMAND starts with a single character. Commands with no arguments are:\n\n  !  Run this command when the ADDRESS _didn't_ match.\n  {  Start new command block, continuing until a corresponding \"}\".\n     Command blocks nest and can have ADDRESSes applying to the whole block.\n  }  End command block (this COMMAND cannot have an address)\n  d  Delete this line and move on to the next one\n     (ignores remaining COMMANDs)\n  D  Delete one line of input and restart command SCRIPT (same as \"d\"\n     unless you've glued lines together with \"N\" or similar)\n  g  Get remembered line (overwriting current line)\n  G  Get remembered line (appending to current line)\n  h  Remember this line (overwriting remembered line)\n  H  Remember this line (appending to remembered line, if any)\n  l  Print line escaping \\abfrtv (but not \\n), octal escape other nonprintng\n     chars, wrap lines to terminal width with \\, append $ to end of line.\n  n  Print default output and read next line over current line (quit at EOF)\n  N  Append \\n and next line of input to this line. Quit at EOF without\n     default output. Advances line counter for ADDRESS and \"=\".\n  p  Print this line\n  P  Print this line up to first newline (from \"N\")\n  q  Quit (print default output, no more commands processed or lines read)\n  x  Exchange this line with remembered line (overwrite in both directions)\n  =  Print the current line number (plus newline)\n  #  Comment, ignores rest of this line of SCRIPT (until newline)\n\nCommands that take an argument:\n\n  : LABEL    Target for jump commands\n  a TEXT     Append text to output before reading next line\n  b LABEL    Branch, jumps to :LABEL (with no LABEL to end of SCRIPT)\n  c TEXT     Delete matching ADDRESS range and output TEXT instead\n  i TEXT     Insert text (output immediately)\n  r FILE     Append contents of FILE to output before reading next line.\n  s/S/R/F    Search for regex S replace match with R using flags F. Delimiter\n             is anything but \\n or \\, escape with \\ to use in S or R. Printf\n             escapes work. Unescaped & in R becomes full matched text, \\1\n             through \\9 = parenthetical subexpression from S. \\ at end of\n             line appends next line of SCRIPT. The flags in F are:\n             [0-9]    A number N, substitute only Nth match\n             g        Global, substitute all matches\n             i/I      Ignore case when matching\n             p        Print resulting line when match found and replaced\n             w [file] Write (append) line to file when match replaced\n  t LABEL    Test, jump if s/// command matched this line since last test\n  T LABEL    Test false, jump to :LABEL only if no s/// found a match\n  w FILE     Write (append) line to file\n  y/old/new/ Change each character in 'old' to corresponding character\n             in 'new' (with standard backslash escapes, delimiter can be\n             any repeated character except \\ or \\n)\n\nThe TEXT arguments (to a c i) may end with an unescaped \"\\\" to append\nthe next line (leading whitespace is not skipped), and treat \";\" as a\nliteral character (use \"\\;\" instead)."
+#define HELP_sed "usage: sed [-inrszE] [-e SCRIPT]...|SCRIPT [-f SCRIPT_FILE]... [FILE...]\n\nStream editor. Apply editing SCRIPTs to lines of input.\n\n-e	Add SCRIPT to list\n-f	Add contents of SCRIPT_FILE to list\n-i	Edit each file in place (-iEXT keeps backup file with extension EXT)\n-n	No default output (use the p command to output matched lines)\n-r	Use extended regular expression syntax\n-E	POSIX alias for -r\n-s	Treat input files separately (implied by -i)\n-z	Use \\0 rather than \\n as input line separator\n\nA SCRIPT is one or more COMMANDs separated by newlines or semicolons.\nAll -e SCRIPTs are combined as if separated by newlines, followed by all -f\nSCRIPT_FILEs. If no -e or -f then first argument is the SCRIPT.\n\nCOMMANDs apply to every line unless prefixed with an ADDRESS of the form:\n\n  [ADDRESS[,ADDRESS]][!]COMMAND\n\nADDRESS is a line number (starting at 1), a /REGULAR EXPRESSION/, or $ for\nlast line (-s or -i makes it last line of each file). One address matches one\nline, ADDRESS,ADDRESS matches from first to second inclusive. Two regexes can\nmatch multiple ranges. ADDRESS,+N ends N lines later. ! inverts the match.\n\nREGULAR EXPRESSIONS start and end with the same character (anything but\nbackslash or newline). To use the delimiter in the regex escape it with a\nbackslash, and printf escapes (\\abcefnrtv and octal, hex, and unicode) work.\nAn empty regex repeats the previous one. ADDRESS regexes require any\nfirst delimiter except / to be \\escaped to distinguish it from COMMANDs.\n\nSed reads each line of input, processes it, and writes it out or discards it\nbefore reading the next. Sed can remember one additional line in a separate\nbuffer (the h, H, g, G, and x commands), and can read the next line of input\nearly (the n and N commands), but otherwise operates on individual lines.\n\nEach COMMAND starts with a single character. Commands with no arguments are:\n\n  !  Run this command when the ADDRESS _didn't_ match.\n  {  Start new command block, continuing until a corresponding \"}\".\n     Command blocks nest and can have ADDRESSes applying to the whole block.\n  }  End command block (this COMMAND cannot have an address)\n  d  Delete this line and move on to the next one\n     (ignores remaining COMMANDs)\n  D  Delete one line of input and restart command SCRIPT (same as \"d\"\n     unless you've glued lines together with \"N\" or similar)\n  g  Get remembered line (overwriting current line)\n  G  Get remembered line (appending to current line)\n  h  Remember this line (overwriting remembered line)\n  H  Remember this line (appending to remembered line, if any)\n  l  Print line escaping \\abfrtvn, octal escape other nonprintng chars,\n     wrap lines to terminal width with \\, append $ to end of line.\n  n  Print default output and read next line over current line (quit at EOF)\n  N  Append \\n and next line of input to this line. Quit at EOF without\n     default output. Advances line counter for ADDRESS and \"=\".\n  p  Print this line\n  P  Print this line up to first newline (from \"N\")\n  q  Quit (print default output, no more commands processed or lines read)\n  x  Exchange this line with remembered line (overwrite in both directions)\n  =  Print the current line number (plus newline)\n  #  Comment, ignores rest of this line of SCRIPT (until newline)\n\nCommands that take an argument:\n\n  : LABEL    Target for jump commands\n  a TEXT     Append text to output before reading next line\n  b LABEL    Branch, jumps to :LABEL (with no LABEL to end of SCRIPT)\n  c TEXT     Delete matching ADDRESS range and output TEXT instead\n  i TEXT     Insert text (output immediately)\n  r FILE     Append contents of FILE to output before reading next line.\n  s/S/R/F    Search for regex S replace match with R using flags F. Delimiter\n             is anything but \\n or \\, escape with \\ to use in S or R. Printf\n             escapes work. Unescaped & in R becomes full matched text, \\1\n             through \\9 = parenthetical subexpression from S. \\ at end of\n             line appends next line of SCRIPT. The flags in F are:\n             [0-9]    A number N, substitute only Nth match\n             g        Global, substitute all matches\n             i/I      Ignore case when matching\n             p        Print resulting line when match found and replaced\n             w [file] Write (append) line to file when match replaced\n  t LABEL    Test, jump if s/// command matched this line since last test\n  T LABEL    Test false, jump to :LABEL only if no s/// found a match\n  w FILE     Write (append) line to file\n  y/old/new/ Change each character in 'old' to corresponding character\n             in 'new' (with standard backslash escapes, delimiter can be\n             any repeated character except \\ or \\n)\n\nThe TEXT arguments (to a c i) may end with an unescaped \"\\\" to append\nthe next line (leading whitespace is not skipped), and treat \";\" as a\nliteral character (use \"\\;\" instead)."
 
 #define HELP_rmdir "usage: rmdir [-p] [DIR...]\n\nRemove one or more directories.\n\n-p	Remove path\n--ignore-fail-on-non-empty	Ignore failures caused by non-empty directories"
 
@@ -584,7 +598,7 @@
 
 #define HELP_mkdir "usage: mkdir [-vp] [-m MODE] [DIR...]\n\nCreate one or more directories.\n\n-m	Set permissions of directory to mode\n-p	Make parent directories as needed\n-v	Verbose"
 
-#define HELP_ls "usage: ls [-ACFHLRSZacdfhiklmnpqrstuwx1] [--color[=auto]] [FILE...]\n\nList files.\n\nwhat to show:\n-a  all files including .hidden    -b  escape nongraphic chars\n-c  use ctime for timestamps       -d  directory, not contents\n-i  inode number                   -p  put a '/' after dir names\n-q  unprintable chars as '?'       -s  storage used (1024 byte units)\n-u  use access time for timestamps -A  list all files but . and ..\n-H  follow command line symlinks   -L  follow symlinks\n-R  recursively list in subdirs    -F  append /dir *exe @sym |FIFO\n-Z  security context\n\noutput formats:\n-1  list one file per line         -C  columns (sorted vertically)\n-g  like -l but no owner           -h  human readable sizes\n-l  long (show full details)       -m  comma separated\n-n  like -l but numeric uid/gid    -o  like -l but no group\n-w  set column width               -x  columns (horizontal sort)\n-ll long with nanoseconds (--full-time)\n--color  device=yellow  symlink=turquoise/red  dir=blue  socket=purple\n         files: exe=green  suid=red  suidfile=redback  stickydir=greenback\n         =auto means detect if output is a tty.\n\nsorting (default is alphabetical):\n-f  unsorted    -r  reverse    -t  timestamp    -S  size"
+#define HELP_ls "usage: ls [-1ACFHLNRSUXZabcdfghilmnopqrstuwx] [--color[=auto]] [FILE...]\n\nList files\n\nwhat to show:\n-A  all files except . and ..      -a  all files including .hidden\n-b  escape nongraphic chars        -d  directory, not contents\n-F  append /dir *exe @sym |FIFO    -f  files (no sort/filter/format)\n-H  follow command line symlinks   -i  inode number\n-L  follow symlinks                -N  no escaping, even on tty\n-p  put '/' after dir names        -q  unprintable chars as '?'\n-R  recursively list in subdirs    -s  storage used (1024 byte units)\n-Z  security context\n\noutput formats:\n-1  list one file per line         -C  columns (sorted vertically)\n-g  like -l but no owner           -h  human readable sizes\n-l  long (show full details)       -ll long with nanoseconds (--full-time)\n-m  comma separated                -n  long with numeric uid/gid\n-o  long without group column      -r  reverse order\n-w  set column width               -x  columns (horizontal sort)\n\nsort by:  (also --sort=longname,longname... ends with alphabetical)\n-c  ctime      -r  reverse    -S  size     -t  time    -u  atime    -U  none\n-X  extension  -!  dirfirst   -~  nocase\n\n--color  =always (default)  =auto (when stdout is tty) =never\n    exe=green  suid=red  suidfile=redback  stickydir=greenback\n    device=yellow  symlink=turquoise/red  dir=blue  socket=purple\n\nLong output uses -cu for display, use -ltc/-ltu to also sort by ctime/atime."
 
 #define HELP_logger "usage: logger [-s] [-t TAG] [-p [FACILITY.]PRIORITY] [MESSAGE...]\n\nLog message (or stdin) to syslog.\n\n-s	Also write message to stderr\n-t	Use TAG instead of username to identify message source\n-p	Specify PRIORITY with optional FACILITY. Default is \"user.notice\""
 
@@ -614,7 +628,7 @@
 
 #define HELP_getconf "usage: getconf -a [PATH] | -l | NAME [PATH]\n\nGet system configuration values. Values from pathconf(3) require a path.\n\n-a	Show all (defaults to \"/\" if no path given)\n-l	List available value names (grouped by source)"
 
-#define HELP_find "usage: find [-HL] [DIR...] [<options>]\n\nSearch directories for matching files.\nDefault: search \".\", match all, -print matches.\n\n-H  Follow command line symlinks         -L  Follow all symlinks\n\nMatch filters:\n-name  PATTERN   filename with wildcards   -iname      ignore case -name\n-path  PATTERN   path name with wildcards  -ipath      ignore case -path\n-user  UNAME     belongs to user UNAME     -nouser     user ID not known\n-group GROUP     belongs to group GROUP    -nogroup    group ID not known\n-perm  [-/]MODE  permissions (-=min /=any) -prune      ignore dir contents\n-size  N[c]      512 byte blocks (c=bytes) -xdev       only this filesystem\n-links N         hardlink count            -atime N[u] accessed N units ago\n-ctime N[u]      created N units ago       -mtime N[u] modified N units ago\n-inum N          inode number N            -empty      empty files and dirs\n-true            always true               -false      always false\n-context PATTERN security context          -executable access(X_OK) perm+ACL\n-samefile FILE   hardlink to FILE          -quit       exit immediately\n-depth           ignore contents of dir    -maxdepth N at most N dirs down\n-newer FILE      newer mtime than FILE     -mindepth N at least N dirs down\n-newerXY FILE    X=acm time > FILE's Y=acm time (Y=t: FILE is literal time)\n-type [bcdflps]  type is (block, char, dir, file, symlink, pipe, socket)\n\nNumbers N may be prefixed by a - (less than) or + (greater than). Units for\n-Xtime are d (days, default), h (hours), m (minutes), or s (seconds).\n\nCombine matches with:\n!, -a, -o, ( )    not, and, or, group expressions\n\nActions:\n-print  Print match with newline  -print0        Print match with null\n-exec   Run command with path     -execdir       Run command in file's dir\n-ok     Ask before exec           -okdir         Ask before execdir\n-delete Remove matching file/dir  -printf FORMAT Print using format string\n\nCommands substitute \"{}\" with matched file. End with \";\" to run each file,\nor \"+\" (next argument after \"{}\") to collect and run with multiple files.\n\n-printf FORMAT characters are \\ escapes and:\n%b  512 byte blocks used\n%f  basename            %g  textual gid          %G  numeric gid\n%i  decimal inode       %l  target of symlink    %m  octal mode\n%M  ls format type/mode %p  path to file         %P  path to file minus DIR\n%s  size in bytes       %T@ mod time as unixtime\n%u  username            %U  numeric uid          %Z  security context"
+#define HELP_find "usage: find [-HL] [DIR...] [<options>]\n\nSearch directories for matching files.\nDefault: search \".\", match all, -print matches.\n\n-H  Follow command line symlinks         -L  Follow all symlinks\n\nMatch filters:\n-name  PATTERN   filename with wildcards   -iname      ignore case -name\n-path  PATTERN   path name with wildcards  -ipath      ignore case -path\n-user  UNAME     belongs to user UNAME     -nouser     user ID not known\n-group GROUP     belongs to group GROUP    -nogroup    group ID not known\n-perm  [-/]MODE  permissions (-=min /=any) -prune      ignore dir contents\n-size  N[c]      512 byte blocks (c=bytes) -xdev       only this filesystem\n-links N         hardlink count            -empty      empty files and dirs\n-atime N[u]      accessed N units ago      -true       always true\n-ctime N[u]      created N units ago       -false      always false\n-mtime N[u]      modified N units ago      -executable access(X_OK) perm+ACL\n-inum  N         inode number N            -readable   access(R_OK) perm+ACL\n-context PATTERN security context          -depth      contents before dir\n-samefile FILE   hardlink to FILE          -maxdepth N at most N dirs down\n-newer    FILE   newer mtime than FILE     -mindepth N at least N dirs down\n-newerXY  FILE   X=acm time > FILE's Y=acm time (Y=t: FILE is literal time)\n-type [bcdflps]  type is (block, char, dir, file, symlink, pipe, socket)\n\nNumbers N may be prefixed by - (less than) or + (greater than). Units for\n-[acm]time are d (days, default), h (hours), m (minutes), or s (seconds).\n\nCombine matches with:\n!, -a, -o, ( )    not, and, or, group expressions\n\nActions:\n-print  Print match with newline  -print0        Print match with null\n-exec   Run command with path     -execdir       Run command in file's dir\n-ok     Ask before exec           -okdir         Ask before execdir\n-delete Remove matching file/dir  -printf FORMAT Print using format string\n-quit   Exit immediately\n\nCommands substitute \"{}\" with matched file. End with \";\" to run each file,\nor \"+\" (next argument after \"{}\") to collect and run with multiple files.\n\n-printf FORMAT characters are \\ escapes and:\n%b  512 byte blocks used\n%f  basename            %g  textual gid          %G  numeric gid\n%i  decimal inode       %l  target of symlink    %m  octal mode\n%M  ls format type/mode %p  path to file         %P  path to file minus DIR\n%s  size in bytes       %T@ mod time as unixtime\n%u  username            %U  numeric uid          %Z  security context"
 
 #define HELP_file "usage: file [-bhLs] [FILE...]\n\nExamine the given files and describe their content types.\n\n-b	Brief (no filename)\n-h	Don't follow symlinks (default)\n-L	Follow symlinks\n-s	Show block/char device contents"
 
@@ -634,9 +648,9 @@
 
 #define HELP_date "usage: date [-u] [-I RES] [-r FILE] [-d DATE] [+DISPLAY_FORMAT] [-D SET_FORMAT] [SET]\n\nSet/get the current date/time. With no SET shows the current date.\n\n-d	Show DATE instead of current time (convert date format)\n-D	+FORMAT for SET or -d (instead of MMDDhhmm[[CC]YY][.ss])\n-I RES	ISO 8601 with RESolution d=date/h=hours/m=minutes/s=seconds/n=ns\n-r	Use modification time of FILE instead of current date\n-s DATE	Set the system clock to DATE.\n-u	Use UTC instead of current timezone\n\nSupported input formats:\n\nMMDDhhmm[[CC]YY][.ss]     POSIX\n@UNIXTIME[.FRACTION]      seconds since midnight 1970-01-01\nYYYY-MM-DD [hh:mm[:ss]]   ISO 8601\nhh:mm[:ss]                24-hour time today\n\nAll input formats can be followed by fractional seconds, and/or a UTC\noffset such as -0800.\n\nAll input formats can be preceded by TZ=\"id\" to set the input time zone\nseparately from the output time zone. Otherwise $TZ sets both.\n\n+FORMAT specifies display format string using strftime(3) syntax:\n\n%% literal %             %n newline              %t tab\n%S seconds (00-60)       %M minute (00-59)       %m month (01-12)\n%H hour (0-23)           %I hour (01-12)         %p AM/PM\n%y short year (00-99)    %Y year                 %C century\n%a short weekday name    %A weekday name         %u day of week (1-7, 1=mon)\n%b short month name      %B month name           %Z timezone name\n%j day of year (001-366) %d day of month (01-31) %e day of month ( 1-31)\n%N nanosec (output only)\n\n%U Week of year (0-53 start Sunday)   %W Week of year (0-53 start Monday)\n%V Week of year (1-53 start Monday, week < 4 days not part of this year)\n\n%F \"%Y-%m-%d\"   %R \"%H:%M\"        %T \"%H:%M:%S\"        %z  timezone (-0800)\n%D \"%m/%d/%y\"   %r \"%I:%M:%S %p\"  %h \"%b\"              %:z timezone (-08:00)\n%x locale date  %X locale time    %c locale date/time  %s  unix epoch time"
 
-#define HELP_cut "usage: cut [-Ds] [-bcCfF LIST] [-dO DELIM] [FILE...]\n\nPrint selected parts of lines from each FILE to standard output.\n\nEach selection LIST is comma separated, either numbers (counting from 1)\nor dash separated ranges (inclusive, with X- meaning to end of line and -X\nfrom start). By default selection ranges are sorted and collated, use -D\nto prevent that.\n\n-b	Select bytes\n-c	Select UTF-8 characters\n-C	Select unicode columns\n-d	Use DELIM (default is TAB for -f, run of whitespace for -F)\n-D	Don't sort/collate selections or match -fF lines without delimiter\n-f	Select fields (words) separated by single DELIM character\n-F	Select fields separated by DELIM regex\n-O	Output delimiter (default one space for -F, input delim for -f)\n-s	Skip lines without delimiters"
+#define HELP_cut "usage: cut [-Ds] [-bcCfF LIST] [-dO DELIM] [FILE...]\n\nPrint selected parts of lines from each FILE to standard output.\n\nEach selection LIST is comma separated, either numbers (counting from 1)\nor dash separated ranges (inclusive, with X- meaning to end of line and -X\nfrom start). By default selection ranges are sorted and collated, use -D\nto prevent that.\n\n-b	Select bytes (with -n round start/end down to start of utf8 char)\n-c	Select UTF-8 characters\n-C	Select unicode columns\n-d	Use DELIM (default is TAB for -f, run of whitespace for -F)\n-D	Don't sort/collate selections or match -fF lines without delimiter\n-f	Select fields (words) separated by single DELIM character\n-F	Select fields separated by DELIM regex\n-O	Output delimiter (default one space for -F, input delim for -f)\n-s	Skip lines without delimiters"
 
-#define HELP_cpio "usage: cpio -{o|t|i|p DEST} [-v] [--verbose] [-F FILE] [--no-preserve-owner]\n       [ignored: -m -H newc]\n\nCopy files into and out of a \"newc\" format cpio archive.\n\n-F FILE	Use archive FILE instead of stdin/stdout\n-p DEST	Copy-pass mode, copy stdin file list to directory DEST\n-i	Extract from archive into file system (stdin=archive)\n-o	Create archive (stdin=list of files, stdout=archive)\n-t	Test files (list only, stdin=archive, stdout=list of files)\n-d	Create directories if needed\n-u	unlink existing files when extracting\n-v	Verbose\n--no-preserve-owner (don't set ownership during extract)"
+#define HELP_cpio "usage: cpio -{o|t|i|p DEST} [-v] [--verbose] [-F FILE] [-R [USER][:GROUP] [--no-preserve-owner]\n\nCopy files into and out of a \"newc\" format cpio archive.\n\n-d	Create directories if needed\n-F FILE	Use archive FILE instead of stdin/stdout\n-i	Extract from archive into file system (stdin=archive)\n-o	Create archive (stdin=list of files, stdout=archive)\n-p DEST	Copy-pass mode, copy stdin file list to directory DEST\n-R USER	Replace owner with USER[:GROUP]\n-t	Test files (list only, stdin=archive, stdout=list of files)\n-u	Unlink existing files when extracting\n-v	Verbose\n--no-preserve-owner     Don't set ownership during extract"
 
 #define HELP_install "usage: install [-dDpsv] [-o USER] [-g GROUP] [-m MODE] [-t TARGET] [SOURCE...] [DEST]\n\nCopy files and set attributes.\n\n-d	Act like mkdir -p\n-D	Create leading directories for DEST\n-g	Make copy belong to GROUP\n-m	Set permissions to MODE\n-o	Make copy belong to USER\n-p	Preserve timestamps\n-s	Call \"strip -p\"\n-t	Copy files to TARGET dir (no DEST)\n-v	Verbose"
 
@@ -658,8 +672,6 @@
 
 #define HELP_chgrp "usage: chgrp/chown [-RHLP] [-fvh] GROUP FILE...\n\nChange group of one or more files.\n\n-f	Suppress most error messages\n-h	Change symlinks instead of what they point to\n-R	Recurse into subdirectories (implies -h)\n-H	With -R change target of symlink, follow command line symlinks\n-L	With -R change target of symlink, follow all symlinks\n-P	With -R change symlink, do not follow symlinks (default)\n-v	Verbose"
 
-#define HELP_catv "usage: catv [-evt] [FILE...]\n\nDisplay nonprinting characters as escape sequences. Use M-x for\nhigh ascii characters (>127), and ^x for other nonprinting chars.\n\n-e	Mark each newline with $\n-t	Show tabs as ^I\n-v	Don't use ^x or M-x escapes"
-
 #define HELP_cat "usage: cat [-etuv] [FILE...]\n\nCopy (concatenate) files to stdout.  If no files listed, copy from stdin.\nFilename \"-\" is a synonym for stdin.\n\n-e	Mark each newline with $\n-t	Show tabs as ^I\n-u	Copy one byte at a time (slow)\n-v	Display nonprinting characters as escape sequences with M-x for\n	high ascii characters (>127), and ^x for other nonprinting chars"
 
 #define HELP_cal "usage: cal [[[DAY] MONTH] YEAR]\n\nPrint a calendar.\n\nWith one argument, prints all months of the specified year.\nWith two arguments, prints calendar for month and year.\nWith three arguments, highlights day within month and year.\n\n-h	Don't highlight today"
diff --git a/android/mac/generated/newtoys.h b/android/mac/generated/newtoys.h
index ade8831..0680e5d 100644
--- a/android/mac/generated/newtoys.h
+++ b/android/mac/generated/newtoys.h
@@ -1,10 +1,11 @@
-USE_TOYBOX(NEWTOY(toybox, NULL, TOYFLAG_STAYROOT|TOYFLAG_NOHELP))
+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_ACPI(NEWTOY(acpi, "abctV", TOYFLAG_USR|TOYFLAG_BIN))
 USE_GROUPADD(OLDTOY(addgroup, groupadd, TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
 USE_USERADD(OLDTOY(adduser, useradd, TOYFLAG_NEEDROOT|TOYFLAG_UMASK|TOYFLAG_SBIN))
@@ -12,21 +13,20 @@
 USE_ARP(NEWTOY(arp, "vi:nDsdap:A:H:[+Ap][!sd]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_ARPING(NEWTOY(arping, "<1>1s:I:w#<0c#<0AUDbqf[+AU][+Df]", TOYFLAG_USR|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))
-USE_BASE64(NEWTOY(base64, "diw#<0=76[!dw]", TOYFLAG_USR|TOYFLAG_BIN))
+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_BC(NEWTOY(bc, "i(interactive)l(mathlib)q(quiet)s(standard)w(warn)", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
 USE_BLKDISCARD(NEWTOY(blkdiscard, "<1>1f(force)l(length)#<0o(offset)#<0s(secure)z(zeroout)[!sz]", TOYFLAG_BIN))
-USE_BLKID(NEWTOY(blkid, "ULs*[!LU]", TOYFLAG_BIN))
+USE_BLKID(NEWTOY(blkid, "ULo:s*[!LU]", TOYFLAG_BIN))
 USE_BLOCKDEV(NEWTOY(blockdev, "<1>1(setro)(setrw)(getro)(getss)(getbsz)(setbsz)#<0(getsz)(getsize)(getsize64)(getra)(setra)#<0(flushbufs)(rereadpt)",TOYFLAG_SBIN))
 USE_BOOTCHARTD(NEWTOY(bootchartd, 0, TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
 USE_BRCTL(NEWTOY(brctl, "<1", TOYFLAG_USR|TOYFLAG_SBIN))
 USE_BUNZIP2(NEWTOY(bunzip2, "cftkv", TOYFLAG_USR|TOYFLAG_BIN))
 USE_BZCAT(NEWTOY(bzcat, NULL, TOYFLAG_USR|TOYFLAG_BIN))
 USE_CAL(NEWTOY(cal, ">3h", TOYFLAG_USR|TOYFLAG_BIN))
-USE_CAT(NEWTOY(cat, "u"USE_CAT_V("vte"), TOYFLAG_BIN))
-USE_CATV(NEWTOY(catv, USE_CATV("vte"), TOYFLAG_USR|TOYFLAG_BIN))
+USE_CAT(NEWTOY(cat, "uvte", TOYFLAG_BIN))
 USE_SH(NEWTOY(cd, ">1LP[-LP]", TOYFLAG_NOFORK))
 USE_CHATTR(NEWTOY(chattr, "?p#v#R", TOYFLAG_BIN))
 USE_CHCON(NEWTOY(chcon, "<2hvR", TOYFLAG_USR|TOYFLAG_BIN))
@@ -36,19 +36,19 @@
 USE_CHROOT(NEWTOY(chroot, "^<1", TOYFLAG_USR|TOYFLAG_SBIN|TOYFLAG_ARGFAIL(125)))
 USE_CHRT(NEWTOY(chrt, "^mp#<0iRbrfo[!ibrfo]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_CHSH(NEWTOY(chsh, "s:", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
-USE_CHVT(NEWTOY(chvt, "<1", TOYFLAG_USR|TOYFLAG_BIN))
+USE_CHVT(NEWTOY(chvt, "<1>1", TOYFLAG_USR|TOYFLAG_BIN))
 USE_CKSUM(NEWTOY(cksum, "HIPLN", TOYFLAG_BIN))
 USE_CLEAR(NEWTOY(clear, NULL, TOYFLAG_USR|TOYFLAG_BIN))
 USE_CMP(NEWTOY(cmp, "<1>4ls(silent)(quiet)n#<1[!ls]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
 USE_COMM(NEWTOY(comm, "<2>2321", TOYFLAG_USR|TOYFLAG_BIN))
 USE_COUNT(NEWTOY(count, NULL, TOYFLAG_USR|TOYFLAG_BIN))
 USE_CP(NEWTOY(cp, "<1(preserve):;D(parents)RHLPprudaslvnF(remove-destination)fit:T[-HLPd][-niu][+Rr]", TOYFLAG_BIN))
-USE_CPIO(NEWTOY(cpio, "(ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]", TOYFLAG_BIN))
+USE_CPIO(NEWTOY(cpio, "(ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)R(owner):md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]", TOYFLAG_BIN))
 USE_CRC32(NEWTOY(crc32, 0, TOYFLAG_BIN))
 USE_CROND(NEWTOY(crond, "fbSl#<0=8d#<0L:c:[-bf][-LS][-ld]", TOYFLAG_USR|TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
 USE_CRONTAB(NEWTOY(crontab, "c:u:elr[!elr]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
-USE_CUT(NEWTOY(cut, "b*|c*|f*|F*|C*|O(output-delimiter):d:sDn[!cbfF]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_DATE(NEWTOY(date, "d:D:I(iso)(iso-8601):;r:s:u(utc)[!dr]", TOYFLAG_BIN))
+USE_CUT(NEWTOY(cut, "b*|c*|f*|F(regex-fields)*|C*|O(output-delimiter):d:sD(allow-duplicates)n[!cbfF]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_DATE(NEWTOY(date, "d:D:I(iso-8601):;r:s:u(utc)[!dr]", TOYFLAG_BIN))
 USE_DD(NEWTOY(dd, 0, TOYFLAG_USR|TOYFLAG_BIN))
 USE_DEALLOCVT(NEWTOY(deallocvt, ">1", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_NEEDROOT))
 USE_SH(NEWTOY(declare, "pAailunxr", TOYFLAG_NOFORK))
@@ -58,12 +58,12 @@
 USE_DEMO_NUMBER(NEWTOY(demo_number, "D#=3<3M#<0hcdbs", TOYFLAG_BIN))
 USE_DEMO_SCANKEY(NEWTOY(demo_scankey, 0, TOYFLAG_BIN))
 USE_DEMO_UTF8TOWC(NEWTOY(demo_utf8towc, 0, TOYFLAG_USR|TOYFLAG_BIN))
-USE_DEVMEM(NEWTOY(devmem, "<1>3", TOYFLAG_USR|TOYFLAG_BIN))
-USE_DF(NEWTOY(df, "HPkhit*a[-HPh]", TOYFLAG_SBIN))
+USE_DEVMEM(NEWTOY(devmem, "<1>3", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_DF(NEWTOY(df, "HPkhit*a[-HPh]", TOYFLAG_BIN))
 USE_DHCP(NEWTOY(dhcp, "V:H:F:x*r:O*A#<0=20T#<0=3t#<0=3s:p:i:SBRCaovqnbf", TOYFLAG_SBIN|TOYFLAG_ROOTONLY))
 USE_DHCP6(NEWTOY(dhcp6, "r:A#<0T#<0t#<0s:p:i:SRvqnbf", TOYFLAG_SBIN|TOYFLAG_ROOTONLY))
 USE_DHCPD(NEWTOY(dhcpd, ">1P#<0>65535fi:S46[!46]", TOYFLAG_SBIN|TOYFLAG_ROOTONLY))
-USE_DIFF(NEWTOY(diff, "<2>2(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)L(label)*S(starting-file):N(new-file)r(recursive)U(unified)#<0=3", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
+USE_DIFF(NEWTOY(diff, "<2>2(unchanged-line-format):;(old-line-format):;(new-line-format):;(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)S(starting-file):F(show-function-line):;L(label)*N(new-file)r(recursive)U(unified)#<0=3", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
 USE_DIRNAME(NEWTOY(dirname, "<1", TOYFLAG_USR|TOYFLAG_BIN))
 USE_DMESG(NEWTOY(dmesg, "w(follow)CSTtrs#<1n#c[!Ttr][!Cc][!Sw]", TOYFLAG_BIN))
 USE_DNSDOMAINNAME(NEWTOY(dnsdomainname, ">0", TOYFLAG_BIN))
@@ -80,12 +80,12 @@
 USE_EXPAND(NEWTOY(expand, "t*", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
 USE_SH(NEWTOY(export, "np", TOYFLAG_NOFORK))
 USE_EXPR(NEWTOY(expr, NULL, TOYFLAG_USR|TOYFLAG_BIN))
-USE_FACTOR(NEWTOY(factor, 0, TOYFLAG_USR|TOYFLAG_BIN))
+USE_FACTOR(NEWTOY(factor, "?hx", TOYFLAG_USR|TOYFLAG_BIN))
 USE_FALLOCATE(NEWTOY(fallocate, ">1l#|o#", TOYFLAG_USR|TOYFLAG_BIN))
 USE_FALSE(NEWTOY(false, NULL, TOYFLAG_BIN|TOYFLAG_NOHELP|TOYFLAG_MAYFORK))
 USE_FDISK(NEWTOY(fdisk, "C#<0H#<0S#<0b#<512ul", TOYFLAG_SBIN))
 USE_FGREP(OLDTOY(fgrep, grep, TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)|TOYFLAG_LINEBUF))
-USE_FILE(NEWTOY(file, "<1bhLs[!hL]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_FILE(NEWTOY(file, "<1b(brief)hLs[!hL]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_FIND(NEWTOY(find, "?^HL[-HL]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_FLOCK(NEWTOY(flock, "<1>1nsux[-sux]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_FMT(NEWTOY(fmt, "w#<0=75", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
@@ -103,17 +103,22 @@
 USE_GETFATTR(NEWTOY(getfattr, "(only-values)dhn:", TOYFLAG_USR|TOYFLAG_BIN))
 USE_GETOPT(NEWTOY(getopt, "^a(alternative)n:(name)o:(options)l*(long)(longoptions)Tu", TOYFLAG_USR|TOYFLAG_BIN))
 USE_GETTY(NEWTOY(getty, "<2t#<0H:I:l:f:iwnmLh", TOYFLAG_SBIN))
+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_GPIOINFO(NEWTOY(gpiofind, "<1>1", TOYFLAG_USR|TOYFLAG_BIN))
+USE_GPIOFIND(NEWTOY(gpiofind, "<1>1", TOYFLAG_USR|TOYFLAG_BIN))
 USE_GPIOGET(NEWTOY(gpioget, "<2l", TOYFLAG_USR|TOYFLAG_BIN))
-USE_GPIOFIND(NEWTOY(gpioinfo, 0, TOYFLAG_USR|TOYFLAG_BIN))
+USE_GPIOINFO(NEWTOY(gpioinfo, 0, TOYFLAG_USR|TOYFLAG_BIN))
 USE_GPIOSET(NEWTOY(gpioset, "<2l", 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)rRsvwcL(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_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_GROUPADD(NEWTOY(groupadd, "<1>2g#<0S", TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
 USE_GROUPDEL(NEWTOY(groupdel, "<1>2", TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
 USE_GROUPS(NEWTOY(groups, NULL, TOYFLAG_USR|TOYFLAG_BIN))
-USE_GUNZIP(NEWTOY(gunzip, "cdfk123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_GZIP(NEWTOY(gzip,    "ncdfk123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_GUNZIP(NEWTOY(gunzip, "cdfkt123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
+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))
@@ -124,18 +129,19 @@
 USE_HOST(NEWTOY(host, "<1>2avt:", TOYFLAG_USR|TOYFLAG_BIN))
 USE_HOSTID(NEWTOY(hostid, ">0", TOYFLAG_USR|TOYFLAG_BIN))
 USE_HOSTNAME(NEWTOY(hostname, ">1bdsfF:[!bdsf]", TOYFLAG_BIN))
+USE_HTTPD(NEWTOY(httpd, ">1v", TOYFLAG_USR|TOYFLAG_BIN))
 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_I2CDETECT(NEWTOY(i2cdetect, ">3aFlqry[!qr]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_I2CDUMP(NEWTOY(i2cdump, "<2>2fy", TOYFLAG_USR|TOYFLAG_BIN))
-USE_I2CGET(NEWTOY(i2cget, "<3>3fy", TOYFLAG_USR|TOYFLAG_BIN))
-USE_I2CSET(NEWTOY(i2cset, "<4fy", TOYFLAG_USR|TOYFLAG_BIN))
+USE_I2CDETECT(NEWTOY(i2cdetect, ">3aFlqry[!qr]", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_I2CDUMP(NEWTOY(i2cdump, "<2>2fy", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_I2CGET(NEWTOY(i2cget, "<2>3fy", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_I2CSET(NEWTOY(i2cset, "<4fy", TOYFLAG_USR|TOYFLAG_SBIN))
 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_INSMOD(NEWTOY(insmod, "<1", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
-USE_INSTALL(NEWTOY(install, "<1cdDpsvt:m:o:g:", TOYFLAG_USR|TOYFLAG_BIN))
+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))
 USE_IORENICE(NEWTOY(iorenice, "<1>3", TOYFLAG_USR|TOYFLAG_BIN))
 USE_IOTOP(NEWTOY(iotop, ">0AaKO" "Hk*o*p*u*s#<1=7d%<100=3000m#n#<1bq", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT|TOYFLAG_LOCALE))
@@ -163,11 +169,11 @@
 USE_LOGNAME(NEWTOY(logname, ">0", TOYFLAG_USR|TOYFLAG_BIN))
 USE_LOGPATH(NEWTOY(logpath, 0, TOYFLAG_NOHELP|TOYFLAG_USR|TOYFLAG_BIN))
 USE_LOSETUP(NEWTOY(losetup, ">2S(sizelimit)#s(show)ro#j:fdcaD[!afj]", TOYFLAG_SBIN))
-USE_LS(NEWTOY(ls, "(color):;(full-time)(show-control-chars)ZgoACFHLRSabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][!qb]", TOYFLAG_BIN|TOYFLAG_LOCALE))
+USE_LS(NEWTOY(ls, "(sort):(color):;(full-time)(show-control-chars)\241(group-directories-first)\376ZgoACFHLNRSUXabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][-Nqb]", TOYFLAG_BIN|TOYFLAG_LOCALE))
 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@i:", 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_MAN(NEWTOY(man, "k:M:", TOYFLAG_USR|TOYFLAG_BIN))
@@ -186,19 +192,21 @@
 USE_MODINFO(NEWTOY(modinfo, "<1b:k:F:0", TOYFLAG_SBIN))
 USE_MODPROBE(NEWTOY(modprobe, "alrqvsDbd*", TOYFLAG_SBIN))
 USE_MORE(NEWTOY(more, 0, TOYFLAG_USR|TOYFLAG_BIN))
-USE_MOUNT(NEWTOY(mount, "?O:afnrvwt:o*[-rw]", TOYFLAG_BIN|TOYFLAG_STAYROOT))
+USE_MOUNT(NEWTOY(mount, "?RO:afnrvwt:o*[-rw]", TOYFLAG_BIN|TOYFLAG_STAYROOT))
 USE_MOUNTPOINT(NEWTOY(mountpoint, "<1qdx[-dx]", TOYFLAG_BIN))
-USE_MV(NEWTOY(mv, "<1vnF(remove-destination)fit:T[-ni]", TOYFLAG_BIN))
+USE_MV(NEWTOY(mv, "<1v(verbose)nF(remove-destination)fit:T[-ni]", TOYFLAG_BIN))
 USE_NBD_CLIENT(OLDTOY(nbd-client, nbd_client, TOYFLAG_USR|TOYFLAG_BIN))
-USE_NBD_CLIENT(NEWTOY(nbd_client, "<3>3ns", 0))
+USE_NBD_SERVER(OLDTOY(nbd-server, nbd_server, TOYFLAG_USR|TOYFLAG_BIN))
+USE_NBD_CLIENT(NEWTOY(nbd_client, "<3>3b#<1>4294967295=4096ns", 0))
+USE_NBD_SERVER(NEWTOY(nbd_server, "<1>1r", 0))
 USE_NETCAT(OLDTOY(nc, netcat, TOYFLAG_USR|TOYFLAG_BIN))
-USE_NETCAT(NEWTOY(netcat, USE_NETCAT_LISTEN("^tElL")"w#<1W#<1p#<1>65535q#<1s:f:46uU"USE_NETCAT_LISTEN("[!tlL][!Lw]")"[!46U]", TOYFLAG_BIN))
+USE_NETCAT(NEWTOY(netcat, "^tElLw#<1W#<1p#<1>65535q#<1s:f:46uUn[!tlL][!Lw][!Lu][!46U]", TOYFLAG_BIN))
 USE_NETSTAT(NEWTOY(netstat, "pWrxwutneal", TOYFLAG_BIN))
 USE_NICE(NEWTOY(nice, "^<1n#", TOYFLAG_BIN))
 USE_NL(NEWTOY(nl, "v#=1l#w#<0=6b:n:s:E", TOYFLAG_USR|TOYFLAG_BIN))
 USE_NOHUP(NEWTOY(nohup, "<1^", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(125)))
 USE_NPROC(NEWTOY(nproc, "(all)", TOYFLAG_USR|TOYFLAG_BIN))
-USE_NSENTER(NEWTOY(nsenter, "<1F(no-fork)t#<1(target)i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user);", TOYFLAG_USR|TOYFLAG_BIN))
+USE_NSENTER(NEWTOY(nsenter, "<1a(all)F(no-fork)t#<1(target)C(cgroup):; i(ipc):; m(mount):; n(net):; p(pid):; u(uts):; U(user):; ", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
 USE_OD(NEWTOY(od, "j#vw#<1=16N#xsodcbA:t*", TOYFLAG_USR|TOYFLAG_BIN))
 USE_ONEIT(NEWTOY(oneit, "^<1nc:p3[!pn]", TOYFLAG_SBIN))
 USE_OPENVT(NEWTOY(openvt, "^<1c#<1>63sw", TOYFLAG_BIN|TOYFLAG_NEEDROOT))
@@ -223,21 +231,21 @@
 USE_PWGEN(NEWTOY(pwgen, ">2r(remove):c(capitalize)n(numerals)y(symbols)s(secure)B(ambiguous)h(help)C1vA(no-capitalize)0(no-numerals)[-cA][-n0][-C1]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_READAHEAD(NEWTOY(readahead, NULL, TOYFLAG_BIN))
 USE_READELF(NEWTOY(readelf, "<1(dyn-syms)adehlnp:SsWx:", TOYFLAG_USR|TOYFLAG_BIN))
-USE_READLINK(NEWTOY(readlink, "<1nqmef(canonicalize)[-mef]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_REALPATH(OLDTOY(realpath, readlink, TOYFLAG_USR|TOYFLAG_BIN))
+USE_READLINK(NEWTOY(readlink, "<1vnf(canonicalize)emqz[-mef][-qv]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_REALPATH(NEWTOY(realpath, "<1(relative-base):R(relative-to):s(no-symlinks)LPemqz[-Ps][-LP][-me]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_REBOOT(NEWTOY(reboot, "d:fn", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
 USE_RENICE(NEWTOY(renice, "<1gpun#|", TOYFLAG_USR|TOYFLAG_BIN))
 USE_RESET(NEWTOY(reset, 0, TOYFLAG_USR|TOYFLAG_BIN))
 USE_RESTORECON(NEWTOY(restorecon, "<1DFnRrv", TOYFLAG_USR|TOYFLAG_SBIN))
 USE_REV(NEWTOY(rev, NULL, TOYFLAG_USR|TOYFLAG_BIN))
 USE_RFKILL(NEWTOY(rfkill, "<1>2", TOYFLAG_USR|TOYFLAG_SBIN))
-USE_RM(NEWTOY(rm, "fiRrv[-fi]", 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_ROUTE(NEWTOY(route, "?neA:", TOYFLAG_SBIN))
 USE_RTCWAKE(NEWTOY(rtcwake, "(list-modes);(auto)a(device)d:(local)l(mode)m:(seconds)s#(time)t#(utc)u(verbose)v[!alu]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_RUNCON(NEWTOY(runcon, "<2", TOYFLAG_USR|TOYFLAG_SBIN))
-USE_SED(NEWTOY(sed, "(help)(version)e*f*i:;nErz(null-data)s[+Er]", TOYFLAG_BIN|TOYFLAG_LOCALE|TOYFLAG_NOHELP))
+USE_RUNCON(NEWTOY(runcon, "^<2", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_SED(NEWTOY(sed, "(help)(version)(tarxform)e*f*i:;nErz(null-data)s[+Er]", TOYFLAG_BIN|TOYFLAG_LOCALE|TOYFLAG_NOHELP))
 USE_SENDEVENT(NEWTOY(sendevent, "<4>4", TOYFLAG_USR|TOYFLAG_SBIN))
 USE_SEQ(NEWTOY(seq, "<1>3?f:s:w[!fw]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_SH(NEWTOY(set, 0, TOYFLAG_NOFORK))
@@ -253,11 +261,12 @@
 USE_SHA512SUM(OLDTOY(sha512sum, md5sum, TOYFLAG_USR|TOYFLAG_BIN))
 USE_SH(NEWTOY(shift, ">1", TOYFLAG_NOFORK))
 USE_SHRED(NEWTOY(shred, "<1zxus#<1n#<1o#<0f", TOYFLAG_USR|TOYFLAG_BIN))
-USE_SKELETON(NEWTOY(skeleton, "(walrus)(blubber):;(also):e@d*c#b:a", TOYFLAG_USR|TOYFLAG_BIN))
+USE_SHUF(NEWTOY(shuf, "zen#<0", TOYFLAG_USR|TOYFLAG_BIN))
+USE_SKELETON(NEWTOY(skeleton, "(walrus)(blubber):;(also):h(hlong):; g(glong): f(longf):;e@d*c#b:a", TOYFLAG_USR|TOYFLAG_BIN))
 USE_SKELETON_ALIAS(NEWTOY(skeleton_alias, "b#dq", TOYFLAG_USR|TOYFLAG_BIN))
 USE_SLEEP(NEWTOY(sleep, "<1", TOYFLAG_BIN))
 USE_SNTP(NEWTOY(sntp, ">1M :m :Sp:t#<0=1>16asdDqr#<4>17=10[!as]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_SORT(NEWTOY(sort, USE_SORT_FLOAT("g")"S:T:m" "o:k*t:" "xVbMcszdfirun", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
+USE_SORT(NEWTOY(sort, USE_SORT_FLOAT("g")"S:T:m" "o:k*t:" "xVbMCcszdfirun", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
 USE_SH(NEWTOY(source, "<1", TOYFLAG_NOFORK))
 USE_SPLIT(NEWTOY(split, ">2a#<1=2>9b#<1l#<1n#<1[!bl][!bn][!ln]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_STAT(NEWTOY(stat, "<1c:(format)fLt", TOYFLAG_BIN))
@@ -266,7 +275,7 @@
 USE_STTY(NEWTOY(stty, "?aF:g[!ag]", TOYFLAG_BIN))
 USE_SU(NEWTOY(su, "^lmpu:g:c:s:[!lmp]", TOYFLAG_BIN|TOYFLAG_ROOTONLY))
 USE_SULOGIN(NEWTOY(sulogin, "t#<0=0", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
-USE_SWAPOFF(NEWTOY(swapoff, "<1>1", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
+USE_SWAPOFF(NEWTOY(swapoff, "<1>1av", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
 USE_SWAPON(NEWTOY(swapon, "<1>1p#<0>32767d", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
 USE_SWITCH_ROOT(NEWTOY(switch_root, "<2c:h", TOYFLAG_SBIN))
 USE_SYNC(NEWTOY(sync, NULL, TOYFLAG_BIN))
@@ -274,9 +283,9 @@
 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_TAC(NEWTOY(tac, NULL, TOYFLAG_USR|TOYFLAG_BIN))
 USE_TAIL(NEWTOY(tail, "?fFs:c(bytes)-n(lines)-[-cn][-fF]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_TAR(NEWTOY(tar, "&(strip-components)#(selinux)(restrict)(full-time)(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mode):(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)I(use-compress-program):J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):a[!txc][!jzJa]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_TASKSET(NEWTOY(taskset, "<1^pa", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
-USE_TCPSVD(NEWTOY(tcpsvd, "^<3c#=30<1C:b#=20<0u:l:hEv", TOYFLAG_USR|TOYFLAG_BIN))
+USE_TAR(NEWTOY(tar, "&(no-ignore-case)(ignore-case)(no-anchored)(anchored)(no-wildcards)(wildcards)(no-wildcards-match-slash)(wildcards-match-slash)(show-transformed-names)(selinux)(restrict)(full-time)(no-recursion)(null)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(sort);:(mode):(mtime):(group):(owner):(to-command):~(strip-components)(strip)#~(transform)(xform)*o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*I(use-compress-program):C(directory):f(file):as[!txc][!jzJa]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_TASKSET(NEWTOY(taskset, "<1^pa", TOYFLAG_USR|TOYFLAG_BIN))
+USE_TCPSVD(NEWTOY(tcpsvd, "^<3c#=30<1b#=20<0C:u:l:hEv", 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))
@@ -284,7 +293,7 @@
 USE_TFTP(NEWTOY(tftp, "<1b#<8>65464r:l:g|p|[!gp]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_TFTPD(NEWTOY(tftpd, "rcu:l", TOYFLAG_BIN))
 USE_TIME(NEWTOY(time, "<1^pv[-pv]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_MAYFORK))
-USE_TIMEOUT(NEWTOY(timeout, "<2^(foreground)(preserve-status)vk:s(signal):", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(125)))
+USE_TIMEOUT(NEWTOY(timeout, "<2^(foreground)(preserve-status)vk:s(signal):i", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(125)))
 USE_TOP(NEWTOY(top, ">0O*h" "Hk*o*p*u*s#<1d%<100=3000m#n#<1bq[!oO]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
 USE_TOUCH(NEWTOY(touch, "<1acd:fmr:t:h[!dtr]", TOYFLAG_BIN))
 USE_SH(OLDTOY(toysh, sh, TOYFLAG_BIN))
@@ -299,17 +308,17 @@
 USE_TCPSVD(OLDTOY(udpsvd, tcpsvd, TOYFLAG_USR|TOYFLAG_BIN))
 USE_ULIMIT(NEWTOY(ulimit, ">1P#<1SHavutsrRqpnmlifedc[-SH][!apvutsrRqnmlifedc]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_UMOUNT(NEWTOY(umount, "cndDflrat*v[!na]", TOYFLAG_BIN|TOYFLAG_STAYROOT))
-USE_UNAME(NEWTOY(uname, "aomvrns", TOYFLAG_BIN))
+USE_UNAME(NEWTOY(uname, "paomvrns", TOYFLAG_BIN))
 USE_UNICODE(NEWTOY(unicode, "<1", TOYFLAG_USR|TOYFLAG_BIN))
 USE_UNIQ(NEWTOY(uniq, "f#s#w#zicdu", TOYFLAG_USR|TOYFLAG_BIN))
 USE_UNIX2DOS(NEWTOY(unix2dos, 0, TOYFLAG_BIN))
 USE_UNLINK(NEWTOY(unlink, "<1>1", TOYFLAG_USR|TOYFLAG_BIN))
 USE_SH(NEWTOY(unset, "fvn[!fv]", TOYFLAG_NOFORK))
-USE_UNSHARE(NEWTOY(unshare, "<1^f(fork);r(map-root-user);i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user);", TOYFLAG_USR|TOYFLAG_BIN))
+USE_UNSHARE(NEWTOY(unshare, "<1^a(all)f(fork)r(map-root-user)C(cgroup):; i(ipc):; m(mount):; n(net):; p(pid):; u(uts):; U(user):; ", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
 USE_UPTIME(NEWTOY(uptime, ">0ps", TOYFLAG_USR|TOYFLAG_BIN))
 USE_USERADD(NEWTOY(useradd, "<1>2u#<0G:s:g:h:SDH", TOYFLAG_NEEDROOT|TOYFLAG_UMASK|TOYFLAG_SBIN))
 USE_USERDEL(NEWTOY(userdel, "<1>1r", TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
-USE_USLEEP(NEWTOY(usleep, "<1", TOYFLAG_BIN))
+USE_USLEEP(NEWTOY(usleep, "<1>1", TOYFLAG_BIN))
 USE_UUDECODE(NEWTOY(uudecode, ">1o:", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_UMASK))
 USE_UUENCODE(NEWTOY(uuencode, "<1>2m", TOYFLAG_USR|TOYFLAG_BIN))
 USE_UUIDGEN(NEWTOY(uuidgen, ">0r(random)", TOYFLAG_USR|TOYFLAG_BIN))
@@ -319,14 +328,14 @@
 USE_W(NEWTOY(w, NULL, TOYFLAG_USR|TOYFLAG_BIN))
 USE_SH(NEWTOY(wait, "n", TOYFLAG_NOFORK))
 USE_WATCH(NEWTOY(watch, "^<1n%<100=2000tebx", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
-USE_WATCHDOG(NEWTOY(watchdog, "<1>1Ft#=4<1T#=60<1", TOYFLAG_NEEDROOT|TOYFLAG_BIN))
+USE_WATCHDOG(NEWTOY(watchdog, "<1>1Ft#=4<1T#=60<1", TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
 USE_WC(NEWTOY(wc, "mcwl", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
 USE_WGET(NEWTOY(wget, "<1>1(max-redirect)#<0=20d(debug)O(output-document):p(post-data):", TOYFLAG_USR|TOYFLAG_BIN))
 USE_WHICH(NEWTOY(which, "<1a", TOYFLAG_USR|TOYFLAG_BIN))
 USE_WHO(NEWTOY(who, "a", TOYFLAG_USR|TOYFLAG_BIN))
 USE_WHOAMI(OLDTOY(whoami, logname, TOYFLAG_USR|TOYFLAG_BIN))
-USE_XARGS(NEWTOY(xargs, "^E:P#<0=1optrn#<1(max-args)s#0[!0E]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_XXD(NEWTOY(xxd, ">1c#<0>256l#o#g#<1=2iprs#[!rs]", 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_XXD(NEWTOY(xxd, ">1c#<0>256l#o#g#<0=2eiprs#[!rs][!re]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_XZCAT(NEWTOY(xzcat, NULL, TOYFLAG_USR|TOYFLAG_BIN))
 USE_YES(NEWTOY(yes, NULL, TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
-USE_ZCAT(NEWTOY(zcat,     "cdfk123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_ZCAT(NEWTOY(zcat,     "cdfkt123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
diff --git a/configure b/configure
index c718e83..d6bbd7d 100755
--- a/configure
+++ b/configure
@@ -12,7 +12,8 @@
 fi
 
 # Warn about stuff, disable stupid warnings, be 8-bit clean for utf8.
-CFLAGS="$CFLAGS -Wall -Wundef -Wno-char-subscripts -Werror=implicit-function-declaration -Wno-char-subscripts -Wno-pointer-sign -Wno-string-plus-int -funsigned-char"
+[ "${CFLAGS/-funsigned-char//}" == "$CFLAGS" ] &&
+  CFLAGS+=" -Wall -Wundef -Werror=implicit-function-declaration -Wno-char-subscripts -Wno-pointer-sign -funsigned-char"
 
 # Set default values if variable not already set
 : ${CC:=cc} ${HOSTCC:=cc} ${GENDIR:=generated} ${KCONFIG_CONFIG:=.config}
diff --git a/kconfig/Makefile b/kconfig/Makefile
index 2e8e5dc..3bd5f6a 100644
--- a/kconfig/Makefile
+++ b/kconfig/Makefile
@@ -39,6 +39,8 @@
 bsd_defconfig: $(obj)/conf $(KCONFIG_TOP)
 	KCONFIG_ALLCONFIG=$(obj)/freebsd_miniconfig $< -n $(KCONFIG_TOP) > /dev/null
 
+android_defconfig: $(obj)/conf $(KCONFIG_TOP)
+	KCONFIG_ALLCONFIG=$(obj)/android_miniconfig $< -n $(KCONFIG_TOP) > /dev/null
 # Help text used by make help
 help::
 	@echo  '  config	  - Update current config utilising a line-oriented program'
@@ -55,6 +57,7 @@
 	@echo  '                    (NOP binary, starting point for further configuration)'
 	@echo  '  macos_defconfig - Select commands known to build on macosx'
 	@echo  '  bsd_defconfig   - Select commands known to build on freebsd'
+	@echo  '  android_defconfig - Select commands available on android'
 
 # Cheesy build
 
diff --git a/kconfig/android_miniconfig b/kconfig/android_miniconfig
new file mode 100644
index 0000000..4428a2b
--- /dev/null
+++ b/kconfig/android_miniconfig
@@ -0,0 +1,198 @@
+CONFIG_BASENAME=y
+CONFIG_CAL=y
+CONFIG_CAT=y
+CONFIG_CHGRP=y
+CONFIG_CHOWN=y
+CONFIG_CHMOD=y
+CONFIG_CKSUM=y
+CONFIG_CMP=y
+CONFIG_COMM=y
+CONFIG_CP=y
+CONFIG_MV=y
+CONFIG_INSTALL=y
+CONFIG_CPIO=y
+CONFIG_CUT=y
+CONFIG_DATE=y
+CONFIG_DF=y
+CONFIG_DIRNAME=y
+CONFIG_DU=y
+CONFIG_ECHO=y
+CONFIG_ENV=y
+CONFIG_EXPAND=y
+CONFIG_FALSE=y
+CONFIG_FILE=y
+CONFIG_FIND=y
+CONFIG_GETCONF=y
+CONFIG_GREP=y
+CONFIG_HEAD=y
+CONFIG_ICONV=y
+CONFIG_ID=y
+CONFIG_GROUPS=y
+CONFIG_LOGNAME=y
+CONFIG_WHOAMI=y
+CONFIG_KILL=y
+CONFIG_LN=y
+CONFIG_LS=y
+CONFIG_MKDIR=y
+CONFIG_MKFIFO=y
+CONFIG_NICE=y
+CONFIG_NL=y
+CONFIG_NOHUP=y
+CONFIG_OD=y
+CONFIG_PASTE=y
+CONFIG_PATCH=y
+CONFIG_PRINTF=y
+CONFIG_PS=y
+CONFIG_TOP=y
+CONFIG_IOTOP=y
+CONFIG_PGREP=y
+CONFIG_PKILL=y
+CONFIG_PWD=y
+CONFIG_RENICE=y
+CONFIG_RM=y
+CONFIG_RMDIR=y
+CONFIG_SED=y
+CONFIG_SLEEP=y
+CONFIG_SORT=y
+CONFIG_SPLIT=y
+CONFIG_STRINGS=y
+CONFIG_TAIL=y
+CONFIG_TAR=y
+CONFIG_TEE=y
+CONFIG_TEST=y
+CONFIG_TIME=y
+CONFIG_TOUCH=y
+CONFIG_TRUE=y
+CONFIG_TTY=y
+CONFIG_ULIMIT=y
+CONFIG_UNAME=y
+CONFIG_UNIQ=y
+CONFIG_UNLINK=y
+CONFIG_UUDECODE=y
+CONFIG_UUENCODE=y
+CONFIG_WC=y
+CONFIG_XARGS=y
+CONFIG_DD=y
+CONFIG_DIFF=y
+CONFIG_EXPR=y
+CONFIG_GETFATTR=y
+CONFIG_GETOPT=y
+CONFIG_LSOF=y
+CONFIG_MODPROBE=y
+CONFIG_MORE=y
+CONFIG_STTY=y
+CONFIG_TR=y
+CONFIG_TRACEROUTE=y
+CONFIG_VI=y
+CONFIG_ACPI=y
+CONFIG_BASE64=y
+CONFIG_BLKDISCARD=y
+CONFIG_BLKID=y
+CONFIG_BLOCKDEV=y
+CONFIG_CHCON=y
+CONFIG_CHROOT=y
+CONFIG_CHRT=y
+CONFIG_CLEAR=y
+CONFIG_DEVMEM=y
+CONFIG_DOS2UNIX=y
+CONFIG_UNIX2DOS=y
+CONFIG_FALLOCATE=y
+CONFIG_FLOCK=y
+CONFIG_FMT=y
+CONFIG_FREE=y
+CONFIG_FREERAMDISK=y
+CONFIG_FSFREEZE=y
+CONFIG_FSYNC=y
+CONFIG_HELP=y
+CONFIG_HWCLOCK=y
+CONFIG_I2CDETECT=y
+CONFIG_I2CDUMP=y
+CONFIG_I2CGET=y
+CONFIG_I2CSET=y
+CONFIG_INOTIFYD=y
+CONFIG_INSMOD=y
+CONFIG_IONICE=y
+CONFIG_IORENICE=y
+CONFIG_LOSETUP=y
+CONFIG_LSATTR=y
+CONFIG_CHATTR=y
+CONFIG_LSMOD=y
+CONFIG_LSPCI=y
+CONFIG_LSUSB=y
+CONFIG_MAKEDEVS=y
+CONFIG_MKSWAP=y
+CONFIG_MODINFO=y
+CONFIG_MOUNTPOINT=y
+CONFIG_NBD_CLIENT=y
+CONFIG_UNSHARE=y
+CONFIG_NSENTER=y
+CONFIG_PARTPROBE=y
+CONFIG_PIVOT_ROOT=y
+CONFIG_PMAP=y
+CONFIG_PRINTENV=y
+CONFIG_PWDX=y
+CONFIG_READELF=y
+CONFIG_READLINK=y
+CONFIG_REALPATH=y
+CONFIG_REV=y
+CONFIG_RMMOD=y
+CONFIG_RTCWAKE=y
+CONFIG_SETFATTR=y
+CONFIG_SETSID=y
+CONFIG_STAT=y
+CONFIG_SWAPOFF=y
+CONFIG_SWAPON=y
+CONFIG_SYSCTL=y
+CONFIG_TAC=y
+CONFIG_NPROC=y
+CONFIG_TASKSET=y
+CONFIG_TIMEOUT=y
+CONFIG_TRUNCATE=y
+CONFIG_UCLAMPSET=y
+CONFIG_UPTIME=y
+CONFIG_USLEEP=y
+CONFIG_UUIDGEN=y
+CONFIG_VCONFIG=y
+CONFIG_VMSTAT=y
+CONFIG_WATCH=y
+CONFIG_WHICH=y
+CONFIG_XXD=y
+CONFIG_YES=y
+CONFIG_IFCONFIG=y
+CONFIG_MICROCOM=y
+CONFIG_NETCAT=y
+CONFIG_NETSTAT=y
+CONFIG_PING=y
+CONFIG_RFKILL=y
+CONFIG_TUNCTL=y
+CONFIG_DMESG=y
+CONFIG_GZIP=y
+CONFIG_GUNZIP=y
+CONFIG_ZCAT=y
+CONFIG_HOSTNAME=y
+CONFIG_KILLALL=y
+CONFIG_MD5SUM=y
+CONFIG_SHA1SUM=y
+CONFIG_SHA224SUM=y
+CONFIG_SHA256SUM=y
+CONFIG_SHA384SUM=y
+CONFIG_SHA512SUM=y
+CONFIG_MKNOD=y
+CONFIG_MKTEMP=y
+CONFIG_MOUNT=y
+CONFIG_PIDOF=y
+CONFIG_SEQ=y
+CONFIG_SYNC=y
+CONFIG_UMOUNT=y
+CONFIG_GETENFORCE=y
+CONFIG_LOAD_POLICY=y
+CONFIG_RESTORECON=y
+CONFIG_RUNCON=y
+CONFIG_SETENFORCE=y
+CONFIG_TOYBOX_SELINUX=y
+CONFIG_TOYBOX_LIBCRYPTO=y
+CONFIG_TOYBOX_LIBZ=y
+CONFIG_TOYBOX_FLOAT=y
+CONFIG_TOYBOX_HELP=y
+CONFIG_TOYBOX_HELP_DASHDASH=y
+CONFIG_TOYBOX_NORECURSE=y
diff --git a/kconfig/freebsd_miniconfig b/kconfig/freebsd_miniconfig
index 3a6fa80..c945aa4 100644
--- a/kconfig/freebsd_miniconfig
+++ b/kconfig/freebsd_miniconfig
@@ -1,7 +1,6 @@
 CONFIG_BASENAME=y
 CONFIG_CAL=y
 CONFIG_CAT=y
-CONFIG_CATV=y
 CONFIG_CHGRP=y
 CONFIG_CHOWN=y
 CONFIG_CHMOD=y
@@ -12,14 +11,18 @@
 CONFIG_CPIO=y
 CONFIG_CUT=y
 CONFIG_DATE=y
+CONFIG_DF=y
 CONFIG_DIRNAME=y
 CONFIG_DU=y
 CONFIG_ECHO=y
+CONFIG_ENV=y
 CONFIG_EXPAND=y
 CONFIG_FALSE=y
 CONFIG_FILE=y
 CONFIG_FIND=y
 CONFIG_GREP=y
+CONFIG_EGREP=y
+CONFIG_FGREP=y
 CONFIG_HEAD=y
 CONFIG_ICONV=y
 CONFIG_ID=y
@@ -50,13 +53,13 @@
 CONFIG_SORT=y
 CONFIG_SPLIT=y
 CONFIG_STRINGS=y
+CONFIG_TAIL=y
 CONFIG_TEE=y
 CONFIG_TEST=y
 CONFIG_TIME=y
 CONFIG_TOUCH=y
 CONFIG_TRUE=y
 CONFIG_TTY=y
-CONFIG_UNAME=y
 CONFIG_UNIQ=y
 CONFIG_UNLINK=y
 CONFIG_UUDECODE=y
@@ -66,14 +69,16 @@
 CONFIG_XARGS=y
 CONFIG_ACPI=y
 CONFIG_ASCII=y
+CONFIG_UNICODE=y
 CONFIG_BASE64=y
+CONFIG_BASE32=y
 CONFIG_BUNZIP2=y
 CONFIG_BZCAT=y
 CONFIG_CHROOT=y
 CONFIG_CHRT=y
-CONFIG_CHVT=y
 CONFIG_CLEAR=y
 CONFIG_COUNT=y
+CONFIG_DEVMEM=y
 CONFIG_DOS2UNIX=y
 CONFIG_UNIX2DOS=y
 CONFIG_FACTOR=y
@@ -82,13 +87,12 @@
 CONFIG_FMT=y
 CONFIG_FSYNC=y
 CONFIG_HELP=y
-CONFIG_HELP_EXTRAS=y
 CONFIG_HEXEDIT=y
 CONFIG_LSMOD=y
 CONFIG_LSPCI=y
-CONFIG_LSPCI_TEXT=y
 CONFIG_LSUSB=y
 CONFIG_MAKEDEVS=y
+CONFIG_MCOOKIE=y
 CONFIG_MKPASSWD=y
 CONFIG_MKSWAP=y
 CONFIG_MODINFO=y
@@ -96,12 +100,16 @@
 CONFIG_PMAP=y
 CONFIG_PRINTENV=y
 CONFIG_PWDX=y
+CONFIG_PWGEN=y
+CONFIG_READELF=y
 CONFIG_READLINK=y
 CONFIG_REALPATH=y
 CONFIG_RESET=y
 CONFIG_REV=y
 CONFIG_SETSID=y
+CONFIG_SHA3SUM=y
 CONFIG_SHRED=y
+CONFIG_STAT=y
 CONFIG_SYSCTL=y
 CONFIG_TAC=y
 CONFIG_TIMEOUT=y
@@ -109,13 +117,29 @@
 CONFIG_USLEEP=y
 CONFIG_UUIDGEN=y
 CONFIG_VMSTAT=y
-CONFIG_WATCH=y
 CONFIG_W=y
+CONFIG_WATCH=y
 CONFIG_WHICH=y
 CONFIG_XXD=y
 CONFIG_YES=y
+CONFIG_FTPGET=y
+CONFIG_FTPPUT=y
+CONFIG_HOST=y
+CONFIG_HTTPD=y
+CONFIG_MICROCOM=y
+CONFIG_NETCAT=y
+CONFIG_WGET=y
+CONFIG_GUNZIP=y
+CONFIG_ZCAT=y
 CONFIG_HOSTNAME=y
+CONFIG_DNSDOMAINNAME=y
 CONFIG_KILLALL=y
+CONFIG_MD5SUM=y
+CONFIG_SHA1SUM=y
+CONFIG_SHA224SUM=y
+CONFIG_SHA256SUM=y
+CONFIG_SHA384SUM=y
+CONFIG_SHA512SUM=y
 CONFIG_MKNOD=y
 CONFIG_MKTEMP=y
 CONFIG_PIDOF=y
diff --git a/kconfig/lkc.h b/kconfig/lkc.h
index 9b629ff..3b31ccb 100644
--- a/kconfig/lkc.h
+++ b/kconfig/lkc.h
@@ -152,4 +152,8 @@
 }
 #endif
 
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
 #endif /* LKC_H */
diff --git a/kconfig/macos_miniconfig b/kconfig/macos_miniconfig
index 26c21b1..6b9f6b4 100644
--- a/kconfig/macos_miniconfig
+++ b/kconfig/macos_miniconfig
@@ -1,117 +1,129 @@
+CONFIG_ASCII=y
+CONFIG_BASE32=y
+CONFIG_BASE64=y
 CONFIG_BASENAME=y
+CONFIG_BZCAT=y
 CONFIG_CAL=y
 CONFIG_CAT=y
-CONFIG_CAT_V=y
-CONFIG_CATV=y
 CONFIG_CHGRP=y
-CONFIG_CHOWN=y
 CONFIG_CHMOD=y
+CONFIG_CHOWN=y
 CONFIG_CKSUM=y
-CONFIG_CRC32=y
+CONFIG_CLEAR=y
 CONFIG_CMP=y
 CONFIG_COMM=y
+CONFIG_COUNT=y
 CONFIG_CP=y
 CONFIG_CPIO=y
+CONFIG_CRC32=y
 CONFIG_CUT=y
 CONFIG_DATE=y
 CONFIG_DF=y
 CONFIG_DIRNAME=y
+CONFIG_DOS2UNIX=y
 CONFIG_DU=y
 CONFIG_ECHO=y
 CONFIG_ENV=y
 CONFIG_EXPAND=y
+CONFIG_FACTOR=y
 CONFIG_FALLOCATE=y
 CONFIG_FALSE=y
 CONFIG_FILE=y
 CONFIG_FIND=y
+CONFIG_FLOCK=y
+CONFIG_FMT=y
+CONFIG_FTPGET=y
+CONFIG_FTPPUT=y
 CONFIG_GETCONF=y
 CONFIG_GREP=y
+CONFIG_GROUPS=y
 CONFIG_HEAD=y
+CONFIG_HELP=y
+CONFIG_HEXEDIT=y
+CONFIG_HOSTNAME=y
+CONFIG_HTTPD=y
 CONFIG_ICONV=y
 CONFIG_ID=y
-CONFIG_GROUPS=y
-CONFIG_LOGNAME=y
-CONFIG_WHOAMI=y
+CONFIG_INSTALL=y
 CONFIG_KILL=y
 CONFIG_KILLALL5=y
 CONFIG_LINK=y
 CONFIG_LN=y
 CONFIG_LOGGER=y
+CONFIG_LOGNAME=y
 CONFIG_LS=y
+CONFIG_MCOOKIE=y
+CONFIG_MD5SUM=y
+CONFIG_MICROCOM=y
 CONFIG_MKDIR=y
 CONFIG_MKFIFO=y
 CONFIG_MKTEMP=y
 CONFIG_MV=y
+CONFIG_NETCAT=y
 CONFIG_NICE=y
 CONFIG_NL=y
 CONFIG_NOHUP=y
 CONFIG_OD=y
 CONFIG_PASTE=y
 CONFIG_PATCH=y
+CONFIG_PRINTENV=y
 CONFIG_PRINTF=y
 CONFIG_PWD=y
+CONFIG_PWDX=y
+CONFIG_PWGEN=y
+CONFIG_READELF=y
+CONFIG_READLINK=y
+CONFIG_REALPATH=y
 CONFIG_RENICE=y
+CONFIG_REV=y
 CONFIG_RM=y
 CONFIG_RMDIR=y
 CONFIG_SED=y
+CONFIG_SEQ=y
+CONFIG_SETSID=y
+CONFIG_SHA1SUM=y
+CONFIG_SHA224SUM=y
+CONFIG_SHA256SUM=y
+CONFIG_SHA384SUM=y
+CONFIG_SHA3SUM=y
+CONFIG_SHA512SUM=y
+CONFIG_SHRED=y
 CONFIG_SLEEP=y
 CONFIG_SORT=y
 CONFIG_SPLIT=y
 CONFIG_STAT=y
 CONFIG_STRINGS=y
+CONFIG_TAC=y
+CONFIG_TAIL=y
 CONFIG_TAR=y
 CONFIG_TEE=y
 CONFIG_TEST=y
 CONFIG_TIME=y
-CONFIG_TOUCH=y
-CONFIG_TRUE=y
-CONFIG_TTY=y
-CONFIG_UNAME=y
-CONFIG_UNIQ=y
-CONFIG_UNLINK=y
-CONFIG_UUDECODE=y
-CONFIG_UUENCODE=y
-CONFIG_WC=y
-CONFIG_WHO=y
-CONFIG_XARGS=y
-CONFIG_ASCII=y
-CONFIG_BASE64=y
-CONFIG_CLEAR=y
-CONFIG_COUNT=y
-CONFIG_DOS2UNIX=y
-CONFIG_UNIX2DOS=y
-CONFIG_FACTOR=y
-CONFIG_FLOCK=y
-CONFIG_FMT=y
-CONFIG_HELP=y
-CONFIG_HEXEDIT=y
-CONFIG_PRINTENV=y
-CONFIG_PWDX=y
-CONFIG_READLINK=y
-CONFIG_REALPATH=y
-CONFIG_REV=y
-CONFIG_SETSID=y
-CONFIG_TAC=y
 CONFIG_TIMEOUT=y
-CONFIG_TRUNCATE=y
-CONFIG_USLEEP=y
-CONFIG_UUIDGEN=y
-CONFIG_WATCH=y
-CONFIG_W=y
-CONFIG_WHICH=y
-CONFIG_XXD=y
-CONFIG_YES=y
-CONFIG_FTPGET=y
-CONFIG_FTPPUT=y
-CONFIG_MICROCOM=y
-CONFIG_NETCAT=y
-CONFIG_NETCAT_LISTEN=y
-CONFIG_HOSTNAME=y
-CONFIG_MD5SUM=y
-CONFIG_SHA1SUM=y
-CONFIG_SEQ=y
-CONFIG_TAIL=y
-CONFIG_TOYBOX_SUID=y
+CONFIG_TOUCH=y
 CONFIG_TOYBOX_FLOAT=y
 CONFIG_TOYBOX_HELP=y
 CONFIG_TOYBOX_HELP_DASHDASH=y
+CONFIG_TOYBOX_SUID=y
+CONFIG_TRUE=y
+CONFIG_TRUNCATE=y
+CONFIG_TTY=y
+CONFIG_UNAME=y
+CONFIG_UNICODE=y
+CONFIG_UNIQ=y
+CONFIG_UNIX2DOS=y
+CONFIG_UNLINK=y
+CONFIG_USLEEP=y
+CONFIG_UUDECODE=y
+CONFIG_UUENCODE=y
+CONFIG_UUIDGEN=y
+CONFIG_W=y
+CONFIG_WATCH=y
+CONFIG_WC=y
+CONFIG_WHICH=y
+CONFIG_WHO=y
+CONFIG_WHOAMI=y
+CONFIG_XARGS=y
+CONFIG_XXD=y
+CONFIG_YES=y
+CONFIG_ZCAT=y
diff --git a/lib/args.c b/lib/args.c
index 2b8da7c..5325827 100644
--- a/lib/args.c
+++ b/lib/args.c
@@ -65,19 +65,19 @@
 //     % time offset in milliseconds with optional s/m/h/d suffix
 //     (longopt)
 //     | this is required. If more than one marked, only one required.
-//     ; long option's argument is optional (can only be supplied with --opt=)
+//     ; Option's argument is optional, and must be collated: -aARG or --a=ARG
 //     ^ Stop parsing after encountering this argument
 //    " " (space char) the "plus an argument" must be separate
 //        I.E. "-j 3" not "-j3". So "kill -stop" != "kill -s top"
 //
 //   At the beginning of the get_opt string (before any options):
-//     ^ stop at first nonoption argument
 //     <0 die if less than # leftover arguments (default 0)
 //     >9 die if > # leftover arguments (default MAX_INT)
-//     ? Allow unknown arguments (pass them through to command).
-//     & first arg has imaginary dash (ala tar/ps/ar) which sets FLAGS_NODASH
 //     0 Include argv[0] in optargs
-//     note: ^ and ? implied when no options
+//     ^ stop at first nonoption argument
+//     ? Pass unknown arguments through to command (implied when no flags).
+//     & first arg has imaginary dash (ala tar/ps/ar) which sets FLAGS_NODASH
+//     ~ Collate following bare longopts (as if under short opt, repeatable)
 //
 //   At the end: [groups] of previously seen options
 //     - Only one in group (switch off)    [-abc] means -ab=-b, -ba=-a, -abc=-c
@@ -85,7 +85,7 @@
 //     ! More than one in group is error   [!abc] means -ab calls error_exit()
 //       primarily useful if you can switch things back off again.
 //
-//   You may use octal escapes with the high bit (127) set to use a control
+//   You may use octal escapes with the high bit (128) set to use a control
 //   character as an option flag. For example, \300 would be the option -@
 
 // Notes from getopt man page
@@ -131,25 +131,31 @@
   unsigned excludes, requires;
 };
 
+static void forget_arg(struct opts *opt)
+{
+  if (opt->arg) {
+    if (opt->type=='*') llist_traverse((void *)*opt->arg, free);
+    *opt->arg = 0;
+  }
+}
+
 // Use getoptflagstate to parse one command line option from argv
-static int gotflag(struct getoptflagstate *gof, struct opts *opt, int shrt)
+// Sets flags, saves/clears opt->arg, advances gof->arg/gof->argc as necessary
+static void gotflag(struct getoptflagstate *gof, struct opts *opt, int longopt)
 {
   unsigned long long i;
+  struct opts *and;
+  char *arg;
   int type;
 
   // Did we recognize this option?
-  if (!opt) {
-    if (gof->noerror) return 1;
-    help_exit("Unknown option '%s'", gof->arg);
-  }
+  if (!opt) help_exit("Unknown option '%s'", gof->arg);
 
   // Might enabling this switch off something else?
   if (toys.optflags & opt->dex[0]) {
-    struct opts *clr;
-
     // Forget saved argument for flag we switch back off
-    for (clr=gof->opts, i=1; clr; clr = clr->next, i<<=1)
-      if (clr->arg && (i & toys.optflags & opt->dex[0])) *clr->arg = 0;
+    for (and = gof->opts, i = 1; and; and = and->next, i<<=1)
+      if (i & toys.optflags & opt->dex[0]) forget_arg(and);
     toys.optflags &= ~opt->dex[0];
   }
 
@@ -159,72 +165,63 @@
   if (opt->flags&2) gof->stopearly=2;
 
   if (toys.optflags & gof->excludes) {
-    struct opts *bad;
-
-    for (bad=gof->opts, i=1; bad ;bad = bad->next, i<<=1) {
-      if (opt == bad || !(i & toys.optflags)) continue;
-      if (toys.optflags & bad->dex[2]) break;
+    for (and = gof->opts, i = 1; and; and = and->next, i<<=1) {
+      if (opt == and || !(i & toys.optflags)) continue;
+      if (toys.optflags & and->dex[2]) break;
     }
-    if (bad) help_exit("No '%c' with '%c'", opt->c, bad->c);
+    if (and) help_exit("No '%c' with '%c'", opt->c, and->c);
   }
 
-  // Does this option take an argument?
-  if (!gof->arg || (shrt && !gof->arg[1])) {
-    gof->arg = 0;
-    if (opt->flags & 8) return 0;
-    gof->arg = "";
-  } else gof->arg++;
-  type = opt->type;
+  // Are we NOT saving an argument? (Type 0, '@', unattached ';', short ' ')
+  if (*(arg = gof->arg)) gof->arg++;
+  if ((type = opt->type) == '@') {
+    ++*opt->arg;
+    return;
+  }
+  if (!longopt && *gof->arg && (opt->flags & 4)) return forget_arg(opt);
+  if (!type || (!arg[!longopt] && (opt->flags & 8))) return forget_arg(opt);
 
-  if (type == '@') ++*(opt->arg);
-  else if (type) {
-    char *arg = gof->arg;
+  // Handle "-xblah" and "-x blah", but also a third case: "abxc blah"
+  // to make "tar xCjfv blah1 blah2 thingy" work like
+  // "tar -x -C blah1 -j -f blah2 -v thingy"
 
-    // Handle "-xblah" and "-x blah", but also a third case: "abxc blah"
-    // to make "tar xCjfv blah1 blah2 thingy" work like
-    // "tar -x -C blah1 -j -f blah2 -v thingy"
+  if (longopt && *arg) arg++;
+  else arg = (gof->nodash_now||!*gof->arg) ? toys.argv[++gof->argc] : gof->arg;
+  if (!gof->nodash_now) gof->arg = "";
+  if (!arg) {
+    struct longopts *lo;
 
-    if (gof->nodash_now || (!arg[0] && !(opt->flags & 8)))
-      arg = toys.argv[++gof->argc];
-    if (!arg) {
-      char *s = "Missing argument to ";
-      struct longopts *lo;
-
-      if (opt->c != -1) help_exit("%s-%c", s, opt->c);
-
-      for (lo = gof->longopts; lo->opt != opt; lo = lo->next);
-      help_exit("%s--%.*s", s, lo->len, lo->str);
-    }
-
-    if (type == ':') *(opt->arg) = (long)arg;
-    else if (type == '*') {
-      struct arg_list **list;
-
-      list = (struct arg_list **)opt->arg;
-      while (*list) list=&((*list)->next);
-      *list = xzalloc(sizeof(struct arg_list));
-      (*list)->arg = arg;
-    } else if (type == '#' || type == '-') {
-      long l = 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);
-
-      *(opt->arg) = l;
-    } else if (CFG_TOYBOX_FLOAT && type == '.') {
-      FLOAT *f = (FLOAT *)(opt->arg);
-
-      *f = strtod(arg, &arg);
-      if (opt->val[0].l != LONG_MIN && *f < opt->val[0].f)
-        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);
-
-    if (!gof->nodash_now) gof->arg = "";
+    arg = "Missing argument to ";
+    if (opt->c != -1) help_exit("%s-%c", arg, opt->c);
+    for (lo = gof->longopts; lo->opt != opt; lo = lo->next);
+    help_exit("%s--%.*s", arg, lo->len, lo->str);
   }
 
-  return 0;
+  // Parse argument by type
+  if (type == ':') *(opt->arg) = (long)arg;
+  else if (type == '*') {
+    struct arg_list **list;
+
+    list = (struct arg_list **)opt->arg;
+    while (*list) list=&((*list)->next);
+    *list = xzalloc(sizeof(struct arg_list));
+    (*list)->arg = arg;
+  } else if (type == '#' || type == '-') {
+    long l = 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);
+
+    *(opt->arg) = l;
+  } else if (CFG_TOYBOX_FLOAT && type == '.') {
+    FLOAT *f = (FLOAT *)(opt->arg);
+
+    *f = strtod(arg, &arg);
+    if (opt->val[0].l != LONG_MIN && *f < opt->val[0].f)
+      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
@@ -255,7 +252,7 @@
 
   // Parse option string into a linked list of options with attributes.
 
-  if (!*options) gof->stopearly++, gof->noerror++;
+  if (!*options) gof->noerror++;
   while (*options) {
     char *temp;
 
@@ -270,7 +267,7 @@
       new->val[0].l = LONG_MIN;
       new->val[1].l = LONG_MAX;
     }
-    // Each option must start with "(" or an option character.  (Bare
+    // Each option must start with "(" or an option character. (Bare
     // longopts only come at the start of the string.)
     if (*options == '(' && new->c != -1) {
       char *end;
@@ -312,8 +309,8 @@
       } else error_exit("<>= only after .#%%");
       options = --temp;
 
-    // At this point, we've hit the end of the previous option.  The
-    // current character is the start of a new option.  If we've already
+    // At this point, we've hit the end of the previous option. The
+    // current character is the start of a new option. If we've already
     // assigned an option to this struct, loop to allocate a new one.
     // (It'll get back here afterwards and fall through to next else.)
     } else if (new->c) {
@@ -321,7 +318,7 @@
       continue;
 
     // Claim this option, loop to see what's after it.
-    } else new->c = 127&*options;
+    } else new->c = *options;
 
     options++;
   }
@@ -332,7 +329,8 @@
   for (new = gof->opts; new; new = new->next) {
     unsigned long long u = 1LL<<idx++;
 
-    if (new->c == 1) new->c = 0;
+    if (new->c == 1 || new->c=='~') new->c = 0;
+    else new->c &= 127;
     new->dex[1] = u;
     if (new->flags & 1) gof->requires |= u;
     if (new->type) {
@@ -386,7 +384,7 @@
   struct getoptflagstate gof;
   struct opts *catch;
   unsigned long long saveflags;
-  char *letters[]={"s",""};
+  char *letters[]={"s",""}, *ss;
 
   // Option parsing is a two stage process: parse the option string into
   // a struct opts list, then use that list to process argv[];
@@ -419,6 +417,8 @@
       gof.arg++;
       if (*gof.arg=='-') {
         struct longopts *lo;
+        struct arg_list *al = 0, *al2;
+        int ii;
 
         gof.arg++;
         // Handle --
@@ -427,28 +427,51 @@
           continue;
         }
 
-        // do we match a known --longopt?
+        // unambiguously match the start of a known --longopt?
         check_help(toys.argv+gof.argc);
         for (lo = gof.longopts; lo; lo = lo->next) {
-          if (!strncmp(gof.arg, lo->str, lo->len)) {
-            if (!gof.arg[lo->len]) gof.arg = 0;
-            else if (gof.arg[lo->len] == '=' && lo->opt->type)
-              gof.arg += lo->len;
-            else continue;
-            // It's a match.
-            catch = lo->opt;
-            break;
+          for (ii = 0; ii<lo->len; ii++) if (gof.arg[ii] != lo->str[ii]) break;
+
+          // = only terminates when we can take an argument, not type 0 or '@'
+          if (!gof.arg[ii] || (gof.arg[ii]=='=' && !strchr("@", lo->opt->type)))
+          {
+            al2 = xmalloc(sizeof(struct arg_list));
+            al2->next = al;
+            al2->arg = (void *)lo;
+            al = al2;
+
+            // Exact match is unambigous even when longer options available
+            if (ii==lo->len) {
+              llist_traverse(al, free);
+              al = 0;
+
+              break;
+            }
           }
         }
+        // How many matches?
+        if (al) {
+          *libbuf = 0;
+          if (al->next) for (ss = libbuf, al2 = al; al2; al2 = al2->next) {
+            lo = (void *)al2->arg;
+            ss += sprintf(ss, " %.*s"+(al2==al), lo->len, lo->str);
+          } else lo = (void *)al->arg;
+          llist_traverse(al, free);
+          if (*libbuf) error_exit("bad --%s (%s)", gof.arg, libbuf);
+        }
 
+        // One unambiguous match?
+        if (lo) {
+          catch = lo->opt;
+          while (!strchr("=", *gof.arg)) gof.arg++;
         // Should we handle this --longopt as a non-option argument?
-        if (!lo && gof.noerror) {
+        } else if (gof.noerror) {
           gof.arg -= 2;
           goto notflag;
         }
 
         // Long option parsed, handle option.
-        gotflag(&gof, catch, 0);
+        gotflag(&gof, catch, 1);
         continue;
       }
 
@@ -458,7 +481,7 @@
       else goto notflag;
     }
 
-    // At this point, we have the args part of -args.  Loop through
+    // At this point, we have the args part of -args. Loop through
     // each entry (could be -abc meaning -a -b -c)
     saveflags = toys.optflags;
     while (gof.arg && *gof.arg) {
@@ -466,14 +489,16 @@
       // Identify next option char.
       for (catch = gof.opts; catch; catch = catch->next)
         if (*gof.arg == catch->c)
-          if (!((catch->flags&4) && gof.arg[1])) break;
+          if (!gof.arg[1] || (catch->flags&(4|8))!=4) break;
 
-      // Handle option char (advancing past what was used)
-      if (gotflag(&gof, catch, 1) ) {
+      if (!catch && gof.noerror) {
         toys.optflags = saveflags;
         gof.arg = toys.argv[gof.argc];
         goto notflag;
       }
+
+      // Handle option char (advancing past what was used)
+      gotflag(&gof, catch, 0);
     }
     continue;
 
diff --git a/lib/deflate.c b/lib/deflate.c
index cdc4f8d..a418c21 100644
--- a/lib/deflate.c
+++ b/lib/deflate.c
@@ -17,7 +17,7 @@
   void *fixdisthuff, *fixlithuff;
 
   // CRC
-  void (*crcfunc)(struct deflate *dd, char *data, int len);
+  void (*crcfunc)(struct deflate *dd, char *data, unsigned len);
   unsigned crctable[256], crc;
 
 
@@ -49,16 +49,21 @@
 
 // Advance bitpos without the overhead of recording bits
 // Loads more data when input buffer empty
-static void bitbuf_skip(struct bitbuf *bb, int bits)
+// call with 0 to just load data, returns 0 at EOF
+static int bitbuf_skip(struct bitbuf *bb, int bits)
 {
-  int pos = bb->bitpos + bits, len = bb->len << 3;
+  int pos = bb->bitpos + bits + (bits<0), len;
 
-  while (pos >= len) {
+  while (pos >= (len = bb->len<<3)) {
     pos -= len;
-    len = (bb->len = read(bb->fd, bb->buf, bb->max)) << 3;
-    if (bb->len < 1) perror_exit("inflate EOF");
+    if (1 > (bb->len = read(bb->fd, bb->buf, bb->max))) {
+      if (!bb->len && !bits) break;
+      error_exit("inflate EOF");
+    }
   }
   bb->bitpos = pos;
+
+  return pos<len;
 }
 
 // Optimized single bit inlined version
@@ -67,7 +72,7 @@
   int bufpos = bb->bitpos>>3;
 
   if (bufpos == bb->len) {
-    bitbuf_skip(bb, 0);
+    bitbuf_skip(bb, -1);
     bufpos = 0;
   }
 
@@ -83,7 +88,10 @@
     int click = bb->bitpos >> 3, blow, blen;
 
     // Load more data if buffer empty
-    if (click == bb->len) bitbuf_skip(bb, click = 0);
+    if (click == bb->len) {
+      bitbuf_skip(bb, -1);
+      click = 0;
+    }
 
     // grab bits from next byte
     blow = bb->bitpos & 7;
@@ -194,6 +202,7 @@
 static void inflate(struct deflate *dd, struct bitbuf *bb)
 {
   dd->crc = ~0;
+
   // repeat until spanked
   for (;;) {
     int final, type;
@@ -322,7 +331,7 @@
   while (!final) {
     // Read next half-window of data if we haven't hit EOF yet.
     len = readall(dd->infd, data+(dd->len&32768), 32768);
-    if (len < 0) perror_exit("read"); // todo: add filename
+    if (len < 0) perror_exit("read"); // TODO: add filename
     if (len != 32768) final++;
     if (dd->crcfunc) dd->crcfunc(dd, data+(dd->len&32768), len);
     // dd->len += len;  crcfunc advances len TODO
@@ -411,17 +420,33 @@
   return 1;
 }
 
-static void gzip_crc(struct deflate *dd, char *data, int len)
+static void gzip_crc(struct deflate *dd, char *data, unsigned len)
 {
   int i;
   unsigned crc, *crc_table = dd->crctable;
 
   crc = dd->crc;
-  for (i=0; i<len; i++) crc = crc_table[(crc^data[i])&0xff] ^ (crc>>8);
+  for (i = 0; i<len; i++) crc = crc_table[(crc^data[i])&0xff] ^ (crc>>8);
   dd->crc = crc;
   dd->len += len;
 }
 
+/*
+// Start with crc = 1, or pass in last crc to append more data
+// Deferred modulus good for paged size inputs (can't overflow for ~5500 bytes)
+unsigned adler32(char *buf, unsigned len, unsigned crc)
+{
+  unsigned aa = crc&((1<<16)-1), bb = crc>>16;
+
+  while (len--) {
+    aa += *buf++;
+    bb += aa;
+  }
+
+  return ((bb%65521)<<16)+aa%65521;
+}
+*/
+
 long long gzip_fd(int infd, int outfd)
 {
   struct bitbuf *bb = bitbuf_init(outfd, 4096);
@@ -460,24 +485,27 @@
 {
   struct bitbuf *bb = bitbuf_init(infd, 4096);
   struct deflate *dd = init_deflate(0);
-  long long rc;
-
-  if (!is_gzip(bb)) error_exit("not gzip");
-  dd->outfd = outfd;
+  long long rc = 0;
 
   // Little endian crc table
   crc_init(dd->crctable, 1);
   dd->crcfunc = gzip_crc;
+  dd->outfd = outfd;
 
-  inflate(dd, bb);
+  do {
+    if (!is_gzip(bb)) error_exit("not gzip");
 
-  // tail: crc32, len32
+    inflate(dd, bb);
 
-  bitbuf_skip(bb, (8-bb->bitpos)&7);
-  if (~dd->crc != bitbuf_get(bb, 32) || dd->len != bitbuf_get(bb, 32))
-    error_exit("bad crc");
+    // tail: crc32, len32
+    bitbuf_skip(bb, (8-bb->bitpos)&7);
+    if (~dd->crc != bitbuf_get(bb, 32) || dd->len != bitbuf_get(bb, 32))
+      error_exit("bad crc");
+    rc += dd->len;
 
-  rc = dd->len;
+    bitbuf_skip(bb, (8-bb->bitpos)&7);
+    dd->pos = dd->len = 0;
+  } while (bitbuf_skip(bb, 0));
   free(bb);
   free(dd);
 
diff --git a/lib/dirtree.c b/lib/dirtree.c
index 4023101..00de64e 100644
--- a/lib/dirtree.c
+++ b/lib/dirtree.c
@@ -52,11 +52,11 @@
   }
 
   // Allocate/populate return structure
-  memset(dt = xmalloc((len = sizeof(struct dirtree)+len+1)+linklen), 0,
-    statless ? sizeof(struct dirtree) : offsetof(struct dirtree, st));
+  dt = xmalloc((len = sizeof(struct dirtree)+len+1)+linklen);
+  memset(dt, 0, sizeof(struct dirtree));
   dt->parent = parent;
-  dt->again = statless ? 2 : 0;
-  if (!statless) memcpy(&dt->st, &st, sizeof(struct stat));
+  if (statless) dt->again = DIRTREE_STATLESS;
+  else memcpy(&dt->st, &st, sizeof(struct stat));
   if (name) strcpy(dt->name, name);
   else *dt->name = 0, dt->st.st_mode = S_IFDIR;
   if (linklen) dt->symlink = memcpy(len+(char *)dt, libbuf, linklen);
@@ -72,6 +72,7 @@
   }
   if (parent) parent->symlink = (char *)1;
   free(dt);
+
   return 0;
 }
 
@@ -116,15 +117,25 @@
 static struct dirtree *dirtree_handle_callback(struct dirtree *new,
   int (*callback)(struct dirtree *node))
 {
-  int flags;
+  int flags, df = DIRTREE_RECURSE|DIRTREE_COMEAGAIN|DIRTREE_BREADTH,
+      fd = AT_FDCWD;
 
   if (!new) return DIRTREE_ABORTVAL;
   if (!callback) return new;
   flags = callback(new);
 
-  if (S_ISDIR(new->st.st_mode) && (flags & (DIRTREE_RECURSE|DIRTREE_COMEAGAIN)))
-    flags = dirtree_recurse(new, callback, !*new->name ? AT_FDCWD :
-      openat(dirtree_parentfd(new), new->name, O_CLOEXEC), flags);
+  if (S_ISDIR(new->st.st_mode) && (flags & df)) {
+    // TODO: check openat returned fd for errors... and do what about it?
+    if (*new->name) fd = openat(dirtree_parentfd(new), new->name, O_CLOEXEC);
+    if (flags&DIRTREE_BREADTH) {
+      new->again |= DIRTREE_BREADTH;
+      if ((DIRTREE_ABORT & dirtree_recurse(new, 0, fd, flags)) ||
+          (DIRTREE_ABORT & (flags = callback(new))))
+        return DIRTREE_ABORTVAL;
+    }
+    flags = dirtree_recurse(new, callback, fd, flags);
+    close(fd);
+  }
 
   // Free node that didn't request saving and has no saved children.
   if (!new->child && !(flags & DIRTREE_SAVE)) {
@@ -136,55 +147,62 @@
 }
 
 // Recursively read/process children of directory node, filtering through
-// callback(). Uses and closes supplied ->dirfd.
+// callback().
 
 int dirtree_recurse(struct dirtree *node,
           int (*callback)(struct dirtree *node), int dirfd, int flags)
 {
-  struct dirtree *new, **ddt = &(node->child);
+  struct dirtree *new = 0, *next, **ddt = &(node->child);
   struct dirent *entry;
   DIR *dir = 0;
 
-  // Why doesn't fdopendir() support AT_FDCWD?
+  // fdopendir() doesn't support AT_FDCWD, closedir() closes fd from opendir()
   if (AT_FDCWD == (node->dirfd = dirfd)) dir = opendir(".");
-  else if (node->dirfd != -1) dir = fdopendir(node->dirfd);
+  else if (node->dirfd != -1) dir = fdopendir(xdup(node->dirfd));
+
   if (!dir) {
     if (!(flags & DIRTREE_SHUTUP)) {
       char *path = dirtree_path(node, 0);
       perror_msg_raw(path);
       free(path);
     }
-    close(node->dirfd);
-
-    return flags;
+    goto done;
   }
 
+  // Iterate through stored entries, if any
+  if (callback && *ddt) while (*ddt) {
+    next = (*ddt)->next;
+    if (!(new = dirtree_handle_callback(*ddt, callback))) *ddt = next;
+    else if (new == DIRTREE_ABORTVAL) goto done;
+    else ddt = &new->next;
+
   // according to the fddir() man page, the filehandle in the DIR * can still
   // be externally used by things that don't lseek() it.
-
-  while ((entry = readdir(dir))) {
+  } else while ((entry = readdir(dir))) {
     if ((flags&DIRTREE_PROC) && !isdigit(*entry->d_name)) continue;
+    if ((flags&DIRTREE_BREADTH) && isdotdot(entry->d_name)) continue;
     if (!(new = dirtree_add_node(node, entry->d_name, flags))) continue;
     if (!new->st.st_blksize && !new->st.st_mode)
       new->st.st_mode = entry->d_type<<12;
     new = dirtree_handle_callback(new, callback);
-    if (new == DIRTREE_ABORTVAL) break;
+    if (new == DIRTREE_ABORTVAL) goto done;
     if (new) {
       *ddt = new;
       ddt = &((*ddt)->next);
+      if (flags&DIRTREE_BREADTH) node->extra++;
     }
   }
 
-  if (flags & DIRTREE_COMEAGAIN) {
-    node->again |= 1;
+  if (callback && (flags & DIRTREE_COMEAGAIN)) {
+    node->again |= DIRTREE_COMEAGAIN;
     flags = callback(node);
   }
 
-  // This closes filehandle as well, so note it
+done:
   closedir(dir);
   node->dirfd = -1;
 
-  return flags;
+  return (new == DIRTREE_ABORTVAL) ? DIRTREE_ABORT : flags;
 }
 
 // Create dirtree from path, using callback to filter nodes. If !callback
diff --git a/lib/env.c b/lib/env.c
index facde63..d47e8d2 100644
--- a/lib/env.c
+++ b/lib/env.c
@@ -61,7 +61,7 @@
 
   for (i = 0; environ[i]; i++) {
     // Drop old entry, freeing as appropriate. Assumes no duplicates.
-    if (!memcmp(name, environ[i], len) && environ[i][len]=='=') {
+    if (!smemcmp(name, environ[i], len) && environ[i][len]=='=') {
       if (i<toys.envc-1) toys.envc--;
       else free(environ[i]);
       j++;
diff --git a/lib/lib.c b/lib/lib.c
index cf0a958..c9207a9 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -17,7 +17,7 @@
   if (err<0 && CFG_TOYBOX_HELP)
     fprintf(stderr, " (see \"%s --help\")", toys.which->name);
   if (msg || err) putc('\n', stderr);
-  if (!toys.exitval) toys.exitval++;
+  if (!toys.exitval) toys.exitval = (toys.which->flags>>24) ? : 1;
 }
 
 // These functions don't collapse together because of the va_stuff.
@@ -449,9 +449,9 @@
 // Remove trailing \n
 char *chomp(char *s)
 {
-  char *p = s+strlen(s);
+  char *p;
 
-  while (p>=s && (p[-1]=='\r' || p[-1]=='\n')) *--p = 0;
+  if (s) for (p = s+strlen(s); p>s && (p[-1]=='\r' || p[-1]=='\n'); *--p = 0);
 
   return s;
 }
@@ -519,6 +519,18 @@
   return i;
 }
 
+int same_file(struct stat *st1, struct stat *st2)
+{
+  return st1->st_ino==st2->st_ino && st1->st_dev==st2->st_dev;
+}
+
+int same_dev_ino(struct stat *st, struct dev_ino *di)
+{
+  return st->st_ino==di->ino && st->st_dev==di->dev;
+}
+
+
+
 // Return how long the file at fd is, if there's any way to determine it.
 off_t fdlength(int fd)
 {
@@ -726,7 +738,7 @@
     // Inability to open a file prints a warning, but doesn't exit.
 
     if (!strcmp(*argv, "-")) fd = 0;
-    else if (0>(fd = notstdio(open(*argv, flags, permissions))) && !failok) {
+    else if (0>(fd = xnotstdio(open(*argv, flags, permissions))) && !failok) {
       perror_msg_raw(*argv);
       if (!anyway) continue;
     }
@@ -888,9 +900,14 @@
   toys.signal = sig;
 }
 
+// More or less SIG_DFL that runs our atexit list and can siglongjmp.
 void exit_signal(int sig)
 {
+  sigset_t sigset;
+
   if (sig) toys.exitval = sig|128;
+  sigfillset(&sigset);
+  sigprocmask(SIG_BLOCK, &sigset, 0);
   xexit();
 }
 
@@ -1060,30 +1077,49 @@
   return rc ? s2 : 0;
 }
 
-// return (malloced) relative path to get from "from" to "to"
-char *relative_path(char *from, char *to)
+void *mepcpy(void *to, void *from, unsigned long len)
+{
+  memcpy(to, from, len);
+
+  return ((char *)to)+len;
+}
+
+// return (malloced) relative path to get between two normalized absolute paths
+// normalized: no duplicate / or trailing / or .. or . (symlinks optional)
+char *relative_path(char *from, char *to, int abs)
 {
   char *s, *ret = 0;
   int i, j, k;
 
-  if (!(from = xabspath(from, 0))) return 0;
-  if (!(to = xabspath(to, 0))) goto error;
+  if (abs) {
+    if (!(from = xabspath(from, 0))) return 0;
+    if (!(to = xabspath(to, 0))) goto error;
+  }
 
-  // skip common directories from root
-  for (i = j = 0; from[i] && from[i] == to[i]; i++) if (to[i] == '/') j = i+1;
+  for (i = j = 0;; i++) {
+    if (!from[i] || !to[i]) {
+      if (from[i]=='/' || to[i]=='/' || from[i]==to[i]) j = i;
+      break;
+    }
+    if (from[i] != to[i]) break;
+    if (from[i] == '/') j = i;
+  }
 
   // count remaining destination directories
   for (i = j, k = 0; from[i]; i++) if (from[i] == '/') k++;
-
-  if (!k) ret = xstrdup(to+j);
-  else {
-    s = ret = xmprintf("%*c%s", 3*k, ' ', to+j);
-    while (k--) memcpy(s+3*k, "../", 3);
+  if (!k) {
+    if (to[j]=='/') j++;
+    ret = xstrdup(to[j] ? to+j : ".");
+  } else {
+    s = ret = xmprintf("%*c%s", 3*k-!!k, ' ', to+j);
+    for (i = 0; i<k; i++) s = mepcpy(s, "/.."+!i, 3-!i);
   }
 
 error:
-  free(from);
-  free(to);
+  if (abs) {
+    free(from);
+    free(to);
+  }
 
   return ret;
 }
@@ -1129,8 +1165,7 @@
         char buf[32];
 
         sprintf(buf, "/proc/%u/exe", u);
-        if (stat(buf, &st2)) continue;
-        if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) continue;
+        if (stat(buf, &st2) || !same_file(&st1, &st2)) continue;
         goto match;
       }
 
@@ -1212,7 +1247,7 @@
 void create_uuid(char *uuid)
 {
   // "Set all the ... bits to randomly (or pseudo-randomly) chosen values".
-  xgetrandom(uuid, 16, 0);
+  xgetrandom(uuid, 16);
 
   // "Set the four most significant bits ... of the time_hi_and_version
   // field to the 4-bit version number [4]".
@@ -1459,7 +1494,7 @@
   char *p = pkt;
   int i = 0;
 
-  if (p[257] && memcmp("ustar", p+257, 5)) return 0;
+  if (p[257] && smemcmp("ustar", p+257, 5)) return 0;
   if (p[148] != '0' && p[148] != ' ') return 0;
   sscanf(p+148, "%8o", &i);
 
@@ -1475,14 +1510,15 @@
     {195, "arcv2"}, {40, "arm"}, {183, "arm64"}, {0x18ad, "avr32"},
     {247, "bpf"}, {106, "blackfin"}, {140, "c6x"}, {23, "cell"}, {76, "cris"},
     {252, "csky"}, {0x5441, "frv"}, {46, "h8300"}, {164, "hexagon"},
-    {50, "ia64"}, {88, "m32r"}, {0x9041, "m32r"}, {4, "m68k"}, {174, "metag"},
-    {189, "microblaze"}, {0xbaab, "microblaze-old"}, {8, "mips"},
-    {10, "mips-old"}, {89, "mn10300"}, {0xbeef, "mn10300-old"}, {113, "nios2"},
-    {92, "openrisc"}, {0x8472, "openrisc-old"}, {15, "parisc"}, {20, "ppc"},
-    {21, "ppc64"}, {243, "riscv"}, {22, "s390"}, {0xa390, "s390-old"},
-    {135, "score"}, {42, "sh"}, {2, "sparc"}, {18, "sparc8+"}, {43, "sparc9"},
-    {188, "tile"}, {191, "tilegx"}, {3, "386"}, {6, "486"}, {62, "x86-64"},
-    {94, "xtensa"}, {0xabc7, "xtensa-old"}
+    {50, "ia64"}, {258, "loongarch"}, {88, "m32r"}, {0x9041, "m32r"},
+    {4, "m68k"}, {174, "metag"}, {189, "microblaze"},
+    {0xbaab, "microblaze-old"}, {8, "mips"}, {10, "mips-old"}, {89, "mn10300"},
+    {0xbeef, "mn10300-old"}, {113, "nios2"}, {92, "openrisc"},
+    {0x8472, "openrisc-old"}, {15, "parisc"}, {20, "ppc"}, {21, "ppc64"},
+    {243, "riscv"}, {22, "s390"}, {0xa390, "s390-old"}, {135, "score"},
+    {42, "sh"}, {2, "sparc"}, {18, "sparc8+"}, {43, "sparc9"}, {188, "tile"},
+    {191, "tilegx"}, {3, "386"}, {6, "486"}, {62, "x86-64"}, {94, "xtensa"},
+    {0xabc7, "xtensa-old"}
   };
 
   for (i = 0; i<ARRAY_LEN(types); i++) {
@@ -1491,3 +1527,45 @@
   sprintf(libbuf, "unknown arch %d", type);
   return libbuf;
 }
+
+// Remove octal escapes from string (common in kernel exports)
+void octal_deslash(char *s)
+{
+  char *o = s;
+
+  while (*s) {
+    if (*s == '\\') {
+      int i, oct = 0;
+
+      for (i = 1; i < 4; i++) {
+        if (!isdigit(s[i])) break;
+        oct = (oct<<3)+s[i]-'0';
+      }
+      if (i == 4) {
+        *o++ = oct;
+        s += i;
+        continue;
+      }
+    }
+    *o++ = *s++;
+  }
+
+  *o = 0;
+}
+
+// ASAN flips out about memcmp("a", "abc", 4) but the result is well-defined.
+// This one's guaranteed to stop at len _or_ the first difference.
+int smemcmp(char *one, char *two, unsigned long len)
+{
+  int ii = 0;
+
+  // NULL sorts after anything else
+  if (one == two) return 0;
+  if (!one) return 1;
+  if (!two) return -1;
+
+  while (len--) if ((ii = *one++ - *two++)) break;
+
+  return ii;
+}
+
diff --git a/lib/lib.h b/lib/lib.h
index 70e5bed..6165ac1 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -3,11 +3,6 @@
  * Copyright 2006 Rob Landley <rob@landley.net>
  */
 
-struct ptr_len {
-  void *ptr;
-  long len;
-};
-
 // llist.c
 
 // All these list types can be handled by the same code because first element
@@ -29,10 +24,9 @@
   char *data;
 };
 
-struct num_cache {
-  struct num_cache *next;
-  long long num;
-  char data[];
+struct dev_ino {
+  dev_t dev;
+  ino_t ino;
 };
 
 void llist_free_arg(void *node);
@@ -44,9 +38,6 @@
 void dlist_add_nomalloc(struct double_list **list, struct double_list *new);
 struct double_list *dlist_add(struct double_list **list, char *data);
 void *dlist_terminate(void *list);
-struct num_cache *get_num_cache(struct num_cache *cache, long long num);
-struct num_cache *add_num_cache(struct num_cache **cache, long long num,
-  void *data, int len);
 
 // args.c
 #define FLAGS_NODASH (1LL<<63)
@@ -139,6 +130,7 @@
 pid_t xpopen(char **argv, int *pipe, int isstdout);
 pid_t xpclose(pid_t pid, int pipe);
 int xrun(char **argv);
+char *xrunread(char *argv[], char *to_stdin);
 int xpspawn(char **argv, int*pipes);
 void xaccess(char *path, int flags);
 void xunlink(char *path);
@@ -153,7 +145,7 @@
 void xpipe(int *pp);
 void xclose(int fd);
 int xdup(int fd);
-int notstdio(int fd);
+int xnotstdio(int fd);
 FILE *xfdopen(int fd, char *mode);
 FILE *xfopen(char *path, char *mode);
 size_t xread(int fd, void *buf, size_t len);
@@ -239,6 +231,8 @@
 char *strend(char *str, char *suffix);
 int strstart(char **a, char *b);
 int strcasestart(char **a, char *b);
+int same_file(struct stat *st1, struct stat *st2);
+int same_dev_ino(struct stat *st, struct dev_ino *di);
 off_t fdlength(int fd);
 void loopfiles_rw(char **argv, int flags, int permissions,
   void (*function)(int fd, char *name));
@@ -277,6 +271,8 @@
 unsigned tar_cksum(void *data);
 int is_tar_header(void *pkt);
 char *elf_arch_name(int type);
+void octal_deslash(char *s);
+int smemcmp(char *one, char *two, unsigned long len);
 
 #define HR_SPACE  1 // Space between number and units
 #define HR_B      2 // Use "B" for single byte units
@@ -356,6 +352,8 @@
 char *ntop(struct sockaddr *sa);
 void xsendto(int sockfd, void *buf, size_t len, struct sockaddr *dest);
 int xrecvwait(int fd, char *buf, int len, union socksaddr *sa, int timeout);
+char *escape_url(char *str, char *and);
+char *unescape_url(char *str, int do_cut);
 
 // password.c
 int get_salt(char *salt, char * algo);
@@ -373,6 +371,8 @@
 
 long long gzip_fd(int infd, int outfd);
 long long gunzip_fd(int infd, int outfd);
+long long gunzip_fd_preload(int infd, int outfd, char *buf, unsigned len);
+
 
 // getmountlist.c
 struct mtab_list {
@@ -399,7 +399,8 @@
 void mode_to_string(mode_t mode, char *buf);
 char *getbasename(char *name);
 char *fileunderdir(char *file, char *dir);
-char *relative_path(char *from, char *to);
+void *mepcpy(void *from, void *to, unsigned long len);
+char *relative_path(char *from, char *to, int abs);
 void names_to_pid(char **names, int (*callback)(pid_t pid, char *name),
     int scripts);
 
diff --git a/lib/llist.c b/lib/llist.c
index 6ceb1ce..63a98bb 100644
--- a/lib/llist.c
+++ b/lib/llist.c
@@ -116,32 +116,3 @@
 
   return end;
 }
-
-// Find num in cache
-struct num_cache *get_num_cache(struct num_cache *cache, long long num)
-{
-  while (cache) {
-    if (num==cache->num) return cache;
-    cache = cache->next;
-  }
-
-  return 0;
-}
-
-// Uniquely add num+data to cache. Updates *cache, returns pointer to existing
-// entry if it was already there.
-struct num_cache *add_num_cache(struct num_cache **cache, long long num,
-  void *data, int len)
-{
-  struct num_cache *old = get_num_cache(*cache, num);
-
-  if (old) return old;
-
-  old = xzalloc(sizeof(struct num_cache)+len);
-  old->next = *cache;
-  old->num = num;
-  memcpy(old->data, data, len);
-  *cache = old;
-
-  return 0;
-}
diff --git a/lib/net.c b/lib/net.c
index 414c82a..16a110e 100644
--- a/lib/net.c
+++ b/lib/net.c
@@ -173,3 +173,49 @@
 
   return len;
 }
+
+// Convert space/low ascii to %XX escapes, plus any chars in "and" string.
+// Returns newly allocated copy of string (even if no changes)
+char *escape_url(char *str, char *and)
+{
+  int i, j , count;
+  char *ret QUIET, *ss QUIET;
+
+  for (j = count = 0;;) {
+    for (i = 0;;) {
+      if (str[i] && (str[i]<=' ' || (and && strchr(and, str[i])))) {
+        if (j) ss += sprintf(ss, "%%%02x", str[i]);
+        else count++;
+      } else if (j) *ss++ = str[i];
+      if (!str[i++]) break;
+    }
+    if (j++) break;
+    ret = ss = xmalloc(i+count*2);
+  }
+
+  return ret;
+}
+
+// Convert %XX escapes to character (in place)
+char *unescape_url(char *str, int do_cut)
+{
+  char *to, *cut = do_cut ? strchr(str, '?') : 0;
+  int i;
+
+  for (to = str;;) {
+    if (*str!='%' || !isxdigit(str[1]) || !isxdigit(str[2])) {
+      if (str==cut) {
+        *to = 0;
+        cut++;
+
+        break;
+      } else if (!(*to++ = *str++)) break;
+    } else {
+      sscanf(++str, "%2x", &i);
+      *to++ = i;
+      str += 2;
+    }
+  }
+
+  return cut;
+}
diff --git a/lib/password.c b/lib/password.c
index 3497176..6bea3d7 100644
--- a/lib/password.c
+++ b/lib/password.c
@@ -23,7 +23,7 @@
       if (al[i].id) s += sprintf(s, "$%c$", '0'+al[i].id);
 
       // Read appropriate number of random bytes for salt
-      xgetrandom(libbuf, ((len*6)+7)/8, 0);
+      xgetrandom(libbuf, ((len*6)+7)/8);
 
       // Grab 6 bit chunks and convert to characters in ./0-9a-zA-Z
       for (i = 0; i<len; i++) {
diff --git a/lib/portability.c b/lib/portability.c
index 89744dd..a9f2815 100644
--- a/lib/portability.c
+++ b/lib/portability.c
@@ -30,20 +30,25 @@
 }
 #endif
 
-int xgetrandom(void *buf, unsigned buflen, unsigned flags)
+void xgetrandom(void *buf, unsigned buflen)
 {
   int fd;
 
-#if CFG_TOYBOX_GETRANDOM
-  if (buflen == getrandom(buf, buflen, flags&~WARN_ONLY)) return 1;
-  if (errno!=ENOSYS && !(flags&WARN_ONLY)) perror_exit("getrandom");
+  // Linux keeps getrandom() in <sys/random.h> and getentropy() in <unistd.h>
+  // BSD/macOS only has getentropy(), but it's in <sys/random.h> (to be fair,
+  // they were there first). getrandom() and getentropy() both went into glibc
+  // in the same release (2.25 in 2017), so this test still works.
+#if __has_include(<sys/random.h>)
+  while (buflen) {
+    if (getentropy(buf, fd = buflen>256 ? 256 : buflen)) break;
+    buflen -= fd;
+    buf += fd;
+  }
+  if (!buflen) return;
+  if (errno!=ENOSYS) perror_exit("getrandom");
 #endif
-  fd = xopen(flags ? "/dev/random" : "/dev/urandom",O_RDONLY|(flags&WARN_ONLY));
-  if (fd == -1) return 0;
-  xreadall(fd, buf, buflen);
+  xreadall(fd = xopen("/dev/urandom", O_RDONLY), buf, buflen);
   close(fd);
-
-  return 1;
 }
 
 // Get list of mounted filesystems, including stat and statvfs info.
@@ -92,30 +97,6 @@
 
 #include <mntent.h>
 
-static void octal_deslash(char *s)
-{
-  char *o = s;
-
-  while (*s) {
-    if (*s == '\\') {
-      int i, oct = 0;
-
-      for (i = 1; i < 4; i++) {
-        if (!isdigit(s[i])) break;
-        oct = (oct<<3)+s[i]-'0';
-      }
-      if (i == 4) {
-        *o++ = oct;
-        s += i;
-        continue;
-      }
-    }
-    *o++ = *s++;
-  }
-
-  *o = 0;
-}
-
 // Check if this type matches list.
 // Odd syntax: typelist all yes = if any, typelist all no = if none.
 
@@ -188,7 +169,7 @@
 
 #endif
 
-#if defined(__APPLE__) || defined(__OpenBSD__)
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
 
 #include <sys/event.h>
 
@@ -332,7 +313,7 @@
   return fsetxattr(fd, name, value, size, 0, flags);
 }
 
-#elif !defined(__OpenBSD__)
+#elif !defined(__FreeBSD__) && !defined(__OpenBSD__)
 
 ssize_t xattr_get(const char *path, const char *name, void *value, size_t size)
 {
@@ -533,7 +514,7 @@
   return ((dev&0xfff00000)>>12)|(dev&0xff);
 #elif defined(__APPLE__)
   return dev&0xffffff;
-#elif defined(__OpenBSD__)
+#elif defined(__FreeBSD__) || defined(__OpenBSD__)
   return minor(dev);
 #else
 #error
@@ -546,7 +527,7 @@
   return (dev&0xfff00)>>8;
 #elif defined(__APPLE__)
   return (dev>>24)&0xff;
-#elif defined(__OpenBSD__)
+#elif defined(__FreeBSD__) || defined(__OpenBSD__)
   return major(dev);
 #else
 #error
@@ -559,7 +540,7 @@
   return (minor&0xff)|((major&0xfff)<<8)|((minor&0xfff00)<<12);
 #elif defined(__APPLE__)
   return (minor&0xffffff)|((major&0xff)<<24);
-#elif defined(__OpenBSD__)
+#elif defined(__FreeBSD__) || defined(__OpenBSD__)
   return makedev(major, minor);
 #else
 #error
@@ -568,7 +549,7 @@
 
 char *fs_type_name(struct statfs *statfs)
 {
-#if defined(__APPLE__) || defined(__OpenBSD__)
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
   // macOS has an `f_type` field, but assigns values dynamically as filesystems
   // are registered. They do give you the name directly though, so use that.
   return statfs->f_fstypename;
@@ -582,7 +563,8 @@
     {0x3434, "nilfs"}, {0x6969, "nfs"}, {0x9fa0, "proc"},
     {0x534F434B, "sockfs"}, {0x62656572, "sysfs"}, {0x517B, "smb"},
     {0x4d44, "msdos"}, {0x4006, "fat"}, {0x43415d53, "smackfs"},
-    {0x73717368, "squashfs"}
+    {0x73717368, "squashfs"}, {0xF2F52010, "f2fs"}, {0xE0F5E1E2, "erofs"},
+    {0x2011BAB0, "exfat"},
   };
   int i;
 
@@ -621,44 +603,43 @@
   *size = lab.d_secsize * lab.d_nsectors;
   return status;
 }
-#endif
-
-static ssize_t copy_file_range_wrap(int infd, off_t *inoff, int outfd,
-    off_t *outoff, size_t len, unsigned flags)
-{
-  // glibc added this constant in git at the end of 2017, shipped in 2018-02.
-#if defined(__NR_copy_file_range)
-  return syscall(__NR_copy_file_range, infd, inoff, outfd, outoff, len, flags);
 #else
-  errno = EINVAL;
-  return -1;
-#endif
+int get_block_device_size(int fd, unsigned long long* size)
+{
+  return 0;
 }
+#endif
 
 // Return bytes copied from in to out. If bytes <0 copy all of in to out.
 // If consumed isn't null, amount read saved there (return is written or error)
 long long sendfile_len(int in, int out, long long bytes, long long *consumed)
 {
   long long total = 0, len, ww;
-  int copy_file_range = CFG_TOYBOX_COPYFILERANGE;
+  int try_cfr = 1;
 
   if (consumed) *consumed = 0;
-  if (in<0) return 0;
-  while (bytes != total) {
+  if (in>=0) while (bytes != total) {
     ww = 0;
     len = bytes-total;
 
     errno = 0;
-    if (copy_file_range) {
+    if (try_cfr) {
       if (bytes<0 || bytes>(1<<30)) len = (1<<30);
-      len = copy_file_range_wrap(in, 0, out, 0, len, 0);
-      if (len < 0 && errno == EINVAL) {
-        copy_file_range = 0;
+      // glibc added this constant in git at the end of 2017, shipped 2018-02.
+      // Android's had the constant for years, but you'll get SIGSYS if you use
+      // this system call before Android U (2023's release).
+#if defined(__NR_copy_file_range) && !defined(__ANDROID__)
+      len = syscall(__NR_copy_file_range, in, 0, out, 0, len, 0);
+#else
+      errno = EINVAL;
+      len = -1;
+#endif
+      if (len < 0) {
+        try_cfr = 0;
 
         continue;
       }
-    }
-    if (!copy_file_range) {
+    } else {
       if (bytes<0 || len>sizeof(libbuf)) len = sizeof(libbuf);
       ww = len = read(in, libbuf, len);
     }
@@ -698,7 +679,7 @@
 // glibc requires -lrt for linux syscalls, which pulls in libgcc_eh.a for
 // static linking, and gcc 9.3 leaks pthread calls from that breaking the build
 // These are both just linux syscalls: wrap them ourselves
-#elif !CFG_TOYBOX_HASTIMERS
+#elif defined(__GLIBC__)
 int timer_create_wrap(clockid_t c, struct sigevent *se, timer_t *t)
 {
   // convert overengineered structure to what kernel actually uses
@@ -713,6 +694,12 @@
   return 0;
 }
 
+#if !defined(SYS_timer_settime) && defined(SYS_timer_settime64)
+// glibc does not define defines SYS_timer_settime on 32-bit systems
+// with 64-bit time_t defaults e.g. riscv32
+#define SYS_timer_settime SYS_timer_settime64
+#endif
+
 int timer_settime_wrap(timer_t t, int flags, struct itimerspec *val,
   struct itimerspec *old)
 {
diff --git a/lib/portability.h b/lib/portability.h
index 77b6a2a..f35ce77 100644
--- a/lib/portability.h
+++ b/lib/portability.h
@@ -8,13 +8,6 @@
 // This must come before we #include any system header file to take effect!
 #define _FILE_OFFSET_BITS 64
 
-// For musl
-#define _ALL_SOURCE
-#include <regex.h>
-#ifndef REG_STARTEND
-#define REG_STARTEND 0
-#endif
-
 #ifdef __APPLE__
 // macOS 10.13 doesn't have the POSIX 2008 direct access to timespec in
 // struct stat, but we can ask it to give us something equivalent...
@@ -26,6 +19,27 @@
 #define st_mtim st_mtimespec
 #endif
 
+// For musl
+#define _ALL_SOURCE
+#include <regex.h>
+#ifndef REG_STARTEND
+#define REG_STARTEND 0
+#endif
+
+// for some reason gnu/libc only sets these if you #define ia_ia_stallman_ftaghn
+// despite FreeBSD and MacOS having both with the same value, and bionic's
+// "upstream-openbsd" directory documenting them as "BSD extensions".
+// (The flexible extension would have been an fnmatch() that returns length
+// matched at location so we could check trailing data ourselves, but no.
+// And it's ANSI only case matching instead of UTF8...)
+#include <fnmatch.h>
+#ifndef FNM_LEADING_DIR
+#define FNM_LEADING_DIR   8
+#endif
+#ifndef FNM_CASEFOLD
+#define FNM_CASEFOLD     16
+#endif
+
 // Test for gcc (using compiler builtin #define)
 
 #ifdef __GNUC__
@@ -39,17 +53,13 @@
 #define printf_format
 #endif
 
-// This isn't in the spec, but it's how we determine what libc we're using.
-
-// Types various replacement prototypes need.
-// This also lets us determine what libc we're using. Systems that
-// have <features.h> will transitively include it, and ones that don't --
-// macOS -- won't break.
+// This lets us determine what libc we're using: systems that have <features.h>
+// will transitively include it, and ones that don't (macOS) won't break.
 #include <sys/types.h>
 
 // Various constants old build environments might not have even if kernel does
 
-#ifndef AT_FDCWD
+#ifndef AT_FDCWD             // Kernel commit 5590ff0d5528 2006
 #define AT_FDCWD -100
 #endif
 
@@ -61,11 +71,11 @@
 #define AT_REMOVEDIR 0x200
 #endif
 
-#ifndef RLIMIT_RTTIME
+#ifndef RLIMIT_RTTIME // Commit 78f2c7db6068f 2008
 #define RLIMIT_RTTIME 15
 #endif
 
-// Introduced in Linux 3.1
+// Introduced in Linux 3.1 (Commit 982d816581eee 2011)
 #ifndef SEEK_DATA
 #define SEEK_DATA 3
 #endif
@@ -84,7 +94,7 @@
 // claim it's in the name of Gnu.
 
 #if defined(__GLIBC__)
-// "Function prototypes shall be provided." but aren't.
+// Glibc violates posix: "Function prototypes shall be provided." but aren't.
 // http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html
 char *crypt(const char *key, const char *salt);
 
@@ -97,14 +107,14 @@
 #include <time.h>
 char *strptime(const char *buf, const char *format, struct tm *tm);
 
-// They didn't like posix basename so they defined another function with the
+// Gnu didn't like posix basename so they defined another function with the
 // same name and if you include libgen.h it #defines basename to something
 // else (where they implemented the real basename), and that define breaks
 // the table entry for the basename command. They didn't make a new function
 // with a different name for their new behavior because gnu.
 //
-// Solution: don't use their broken header, provide an inline to redirect the
-// correct name to the broken name.
+// Solution: don't use their broken header and provide an inline to redirect
+// the standard name to the renamed function with the standard behavior.
 
 char *dirname(char *path);
 char *__xpg_basename(char *path);
@@ -114,9 +124,6 @@
   const void *needle, size_t needle_length);
 #endif // defined(glibc)
 
-// getopt_long(), getopt_long_only(), and struct option.
-#include <getopt.h>
-
 #if !defined(__GLIBC__)
 // POSIX basename.
 #include <libgen.h>
@@ -148,6 +155,10 @@
 #define IS_BIG_ENDIAN 0
 #endif
 
+#define bswap_16(x) bswap16(x)
+#define bswap_32(x) bswap32(x)
+#define bswap_64(x) bswap64(x)
+
 #else
 
 #include <byteswap.h>
@@ -229,7 +240,7 @@
 #include <xlocale.h>
 #endif
 
-#if defined(__APPLE__) || defined(__OpenBSD__)
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
 static inline long statfs_bsize(struct statfs *sf) { return sf->f_iosize; }
 static inline long statfs_frsize(struct statfs *sf) { return sf->f_bsize; }
 #else
@@ -240,10 +251,10 @@
 
 // Android is missing some headers and functions
 // "generated/config.h" is included first
-#if CFG_TOYBOX_SHADOW
+#if __has_include(<shadow.h>)
 #include <shadow.h>
 #endif
-#if CFG_TOYBOX_UTMPX
+#if __has_include(<utmpx.h>)
 #include <utmpx.h>
 #else
 struct utmpx {int ut_type;};
@@ -255,6 +266,9 @@
 
 // Some systems don't define O_NOFOLLOW, and it varies by architecture, so...
 #include <fcntl.h>
+#if defined(__APPLE__)
+#define O_PATH 0
+#else
 #ifndef O_NOFOLLOW
 #define O_NOFOLLOW 0
 #endif
@@ -270,6 +284,7 @@
 #ifndef SCHED_RESET_ON_FORK
 #define SCHED_RESET_ON_FORK (1<<30)
 #endif
+#endif
 
 // Glibc won't give you linux-kernel constants unless you say "no, a BUD lite"
 // even though linux has nothing to do with the FSF and never has.
@@ -292,8 +307,12 @@
 pid_t xfork(void);
 #endif
 
-//#define strncpy(...) @@strncpyisbadmmkay@@
-//#define strncat(...) @@strncatisbadmmkay@@
+// gratuitously memsets ALL the extra space with zeroes (not just a terminator)
+// but to make up for it truncating doesn't null terminate the output at all.
+// There are occasions to use it, but it is NOT A GENERAL PURPOSE FUNCTION.
+// #define strncpy(...) @@strncpyisbadmmkay@@
+// strncat writes a null terminator one byte PAST the buffer size it's given.
+#define strncat(...) strncatisbadmmkay(__VA_ARGS__)
 
 // Support building the Android tools on glibc, so hermetic AOSP builds can
 // use toybox before they're ready to switch to host bionic.
@@ -343,10 +362,10 @@
 extern CODE prioritynames[], facilitynames[];
 #endif
 
-#if CFG_TOYBOX_GETRANDOM
+#if __has_include (<sys/random.h>)
 #include <sys/random.h>
 #endif
-int xgetrandom(void *buf, unsigned len, unsigned flags);
+void xgetrandom(void *buf, unsigned len);
 
 // Android's bionic libc doesn't have confstr.
 #ifdef __BIONIC__
@@ -393,7 +412,8 @@
 };
 int timer_create(clock_t c, struct sigevent *se, timer_t *t);
 int timer_settime(timer_t t, int flags, struct itimerspec *new, void *old);
-#elif !CFG_TOYBOX_HASTIMERS
+#elif defined(__GLIBC__)
+// Work around a glibc bug that interacts badly with a gcc bug.
 #include <syscall.h>
 #include <signal.h>
 #include <time.h>
diff --git a/lib/tty.c b/lib/tty.c
index c09413b..3f26976 100644
--- a/lib/tty.c
+++ b/lib/tty.c
@@ -6,6 +6,12 @@
  * \e[#m   - color change           \e[y;xH - jump to x/y pos (1;1 is top left)
  * \e[K    - delete to EOL          \e[25l  - disable cursor (h to enable)
  * \e[1L   - Insert 1 (blank) line  \e[1M   - Delete 1 line (scrolling rest up)
+ * \e[2J   - clear screen
+ *
+ * colors: 0=black 1=red 2=green 3=brown 4=blue 5=purple 6=cyan 7=grey
+ *         +30 foreground, +40 background.
+ *         \e[1m = bright, \e[2m = dark, \e[0m = reset to defaults
+ *         \e[1;32;2;42mhello\e[0m - dark green text on light green background
  */
 
 #include "toys.h"
@@ -16,7 +22,7 @@
 
   for (i = 0; i<3; i++) if (isatty(j = (i+1)%3)) return j;
 
-  return notstdio(open("/dev/tty", O_RDWR));
+  return xnotstdio(open("/dev/tty", O_RDWR));
 }
 
 // Query size of terminal (without ANSI probe fallback).
diff --git a/lib/xwrap.c b/lib/xwrap.c
index 65e9f4f..5ea47d4 100644
--- a/lib/xwrap.c
+++ b/lib/xwrap.c
@@ -251,10 +251,8 @@
 
   // Make the pipes?
   memset(cestnepasun, 0, sizeof(cestnepasun));
-  if (pipes) for (pid = 0; pid < 2; pid++) {
-    if (pipes[pid] != -1) continue;
-    if (pipe(cestnepasun+(2*pid))) perror_exit("pipe");
-  }
+  if (pipes) for (pid = 0; pid < 2; pid++)
+    if (pipes[pid]==-1 && pipe(cestnepasun+(2*pid))) perror_exit("pipe");
 
   if (!(pid = CFG_TOYBOX_FORK ? xfork() : XVFORK())) {
     // Child process: Dance of the stdin/stdout redirection.
@@ -341,7 +339,7 @@
 // Wait for child process to exit, then return adjusted exit code.
 int xwaitpid(pid_t pid)
 {
-  int status;
+  int status = 127<<8;
 
   while (-1 == waitpid(pid, &status, 0) && errno == EINTR) errno = 0;
 
@@ -351,8 +349,8 @@
 int xpclose_both(pid_t pid, int *pipes)
 {
   if (pipes) {
-    close(pipes[0]);
-    close(pipes[1]);
+    if (pipes[0]) close(pipes[0]);
+    if (pipes[1]>1) close(pipes[1]);
   }
 
   return xwaitpid(pid);
@@ -384,6 +382,34 @@
   return xpclose_both(xpopen_both(argv, 0), 0);
 }
 
+// Run child, writing to_stdin, returning stdout or NULL, pass through stderr
+char *xrunread(char *argv[], char *to_stdin)
+{
+  char *result = 0;
+  int pipe[] = {-1, -1}, total = 0, len;
+  pid_t pid;
+
+  pid = xpopen_both(argv, pipe);
+  if (to_stdin && *to_stdin) writeall(*pipe, to_stdin, strlen(to_stdin));
+  close(*pipe);
+  for (;;) {
+    if (0>=(len = readall(pipe[1], libbuf, sizeof(libbuf)))) break;
+    memcpy((result = xrealloc(result, 1+total+len))+total, libbuf, len);
+    total += len;
+    if (len != sizeof(libbuf)) break;
+  }
+  if (result) result[total] = 0;
+  close(pipe[1]);
+
+  if (xwaitpid(pid)) {
+    free(result);
+
+    return 0;
+  }
+
+  return result;
+}
+
 void xaccess(char *path, int flags)
 {
   if (access(path, flags)) perror_exit("Can't access '%s'", path);
@@ -431,9 +457,7 @@
   return fd;
 }
 
-// Move file descriptor above stdin/stdout/stderr, using /dev/null to consume
-// old one. (We should never be called with stdin/stdout/stderr closed, but...)
-int notstdio(int fd)
+int xnotstdio(int fd)
 {
   if (fd<0) return fd;
 
@@ -466,13 +490,13 @@
 // Create a file but don't return stdin/stdout/stderr
 int xcreate(char *path, int flags, int mode)
 {
-  return notstdio(xcreate_stdio(path, flags, mode));
+  return xnotstdio(xcreate_stdio(path, flags, mode));
 }
 
 // Open a file descriptor NOT in stdin/stdout/stderr
 int xopen(char *path, int flags)
 {
-  return notstdio(xopen_stdio(path, flags));
+  return xnotstdio(xopen_stdio(path, flags));
 }
 
 // Open read only, treating "-" as a synonym for stdin, defaulting to warn only
@@ -605,8 +629,8 @@
     }
 
     // Is this a symlink?
-    if (flags & (ABS_KEEP<<!todo)) errno = len = 0;
-    else len = readlinkat(dirfd, new->str, libbuf, sizeof(libbuf));
+    if (flags & (ABS_KEEP<<!todo)) len = 0, errno = EINVAL;
+    else len = readlinkat(dirfd, str, libbuf, sizeof(libbuf));
     if (len>4095) goto error;
 
     // Not a symlink: add to linked list, move dirfd, fail if error
diff --git a/main.c b/main.c
index 9d9d706..b4971bc 100644
--- a/main.c
+++ b/main.c
@@ -76,26 +76,32 @@
 #include "generated/newtoys.h"
 ;
 
-void show_help(FILE *out, int full)
+void show_help(FILE *out, int flags)
 {
   int i = toys.which-toy_list;
   char *s, *ss;
 
-  if (!(full&2))
-    fprintf(out, "Toybox %s"USE_TOYBOX(" multicall binary")"%s\n\n",
-      toybox_version, (CFG_TOYBOX && i) ? " (see toybox --help)"
-      : " (see https://landley.net/toybox)");
-
   if (CFG_TOYBOX_HELP) {
+    if (flags & HELP_HEADER)
+      fprintf(out, "Toybox %s"USE_TOYBOX(" multicall binary")"%s\n\n",
+        toybox_version, (CFG_TOYBOX && i) ? " (see toybox --help)"
+        : " (see https://landley.net/toybox)");
+
     for (;;) {
       s = help_data;
       while (i--) s += strlen(s) + 1;
       // If it's an alias, restart search for real name
       if (*s != 255) break;
       i = toy_find(++s)-toy_list;
+      if ((flags & HELP_SEE) && toy_list[i].flags) {
+        if (flags & HELP_HTML) fprintf(out, "See <a href=#%s>%s</a>\n", s, s);
+        else fprintf(out, "%s see %s\n", toys.which->name, s);
+
+        return;
+      }
     }
 
-    if (full) fprintf(out, "%s\n", s);
+    if (!(flags & HELP_USAGE)) fprintf(out, "%s\n", s);
     else {
       strstart(&s, "usage: ");
       for (ss = s; *ss && *ss!='\n'; ss++);
@@ -119,9 +125,11 @@
     if (toys.which->flags&TOYFLAG_NOHELP) return;
 
   if (!strcmp(*arg, "--help")) {
-    if (CFG_TOYBOX && toys.which == toy_list && arg[1])
+    if (CFG_TOYBOX && toys.which == toy_list && arg[1]) {
+      toys.which = 0;
       if (!(toys.which = toy_find(arg[1]))) unknown(arg[1]);
-    show_help(stdout, 1);
+    }
+    show_help(stdout, HELP_HEADER);
     xexit();
   }
 
@@ -144,16 +152,17 @@
     for (toys.optc = 0; toys.optargs[toys.optc]; toys.optc++);
   }
 
+  // Setup we only want to do once: skip for multiplexer or NOFORK reentry
   if (!(CFG_TOYBOX && which == toy_list) && !(which->flags & TOYFLAG_NOFORK)) {
     toys.old_umask = umask(0);
     if (!(which->flags & TOYFLAG_UMASK)) umask(toys.old_umask);
 
-    // Try user's locale, but merge in the en_US.UTF-8 locale's character
-    // type data if the user's locale isn't UTF-8. (We can't merge in C.UTF-8
-    // because that locale doesn't exist on macOS.)
+    // Try user's locale, but if that isn't UTF-8 merge in a UTF-8 locale's
+    // character type data. (Fall back to en_US for MacOS.)
     setlocale(LC_CTYPE, "");
     if (strcmp("UTF-8", nl_langinfo(CODESET)))
-      uselocale(newlocale(LC_CTYPE_MASK, "en_US.UTF-8", NULL));
+      uselocale(newlocale(LC_CTYPE_MASK, "C.UTF-8", 0) ? :
+        newlocale(LC_CTYPE_MASK, "en_US.UTF-8", 0));
 
     setvbuf(stdout, 0, (which->flags & TOYFLAG_LINEBUF) ? _IOLBF : _IONBF, 0);
   }
diff --git a/mkroot/mkroot.sh b/mkroot/mkroot.sh
new file mode 100755
index 0000000..0447b38
--- /dev/null
+++ b/mkroot/mkroot.sh
@@ -0,0 +1,309 @@
+#!/bin/bash
+
+# ------------------------------ Part 1: Setup -------------------------------
+
+# Clear environment variables by restarting script w/bare minimum passed through
+[ -z "$NOCLEAR" ] && exec env -i NOCLEAR=1 HOME="$HOME" PATH="$PATH" \
+    LINUX="$LINUX" CROSS="$CROSS" CROSS_COMPILE="$CROSS_COMPILE" "$0" "$@"
+
+! [ -d mkroot ] && echo "Run mkroot/mkroot.sh from toybox source dir." && exit 1
+
+# assign command line NAME=VALUE args to env vars, the rest are packages
+for i in "$@"; do
+  [ "${i/=/}" != "$i" ] && export "$i" || { [ "$i" != -- ] && PKG="$PKG $i"; }
+done
+
+# Set default directory locations (overrideable from command line)
+: ${TOP:=$PWD/root} ${BUILD:=$TOP/build} ${LOG:=$BUILD/log}
+: ${AIRLOCK:=$BUILD/airlock} ${CCC:=$PWD/ccc} ${PKGDIR:=$PWD/mkroot/root}
+
+announce() { printf "\033]2;$CROSS $*\007" >/dev/tty; printf "\n=== $*\n";}
+die() { echo "$@" >&2; exit 1; }
+
+# ----- Are we cross compiling (via CROSS_COMPILE= or CROSS=)
+
+if [ -n "$CROSS_COMPILE" ]; then
+  # airlock needs absolute path
+  [ -z "${X:=$(command -v "$CROSS_COMPILE"cc)}" ] && die "no ${CROSS_COMPILE}cc"
+  CROSS_COMPILE="$(realpath -s "${X%cc}")"
+  [ -z "$CROSS" ] && CROSS=${CROSS_COMPILE/*\//} CROSS=${CROSS/-*/}
+
+elif [ -n "$CROSS" ]; then # CROSS=all/allnonstop/$ARCH else list known $ARCHes
+  [ ! -d "$CCC" ] && die "No ccc symlink to compiler directory."
+  TARGETS="$(ls "$CCC" | sed -n 's/-.*//p' | sort -u)"
+
+  if [ "${CROSS::3}" == all ]; then # loop calling ourselves for each target
+    for i in $TARGETS; do
+      "$0" "$@" CROSS=$i || [ "$CROSS" == allnonstop ] || exit 1
+    done; exit
+
+  else # Find matching cross compiler under ccc/ else list available targets
+    CROSS_COMPILE="$(echo "$CCC/$CROSS"-*cross/bin/"$CROSS"*-cc)" # wildcard
+    [ ! -e "$CROSS_COMPILE" ] && echo $TARGETS && exit # list available targets
+    CROSS_COMPILE="${CROSS_COMPILE%cc}" # trim to prefix for cc/ld/as/nm/strip
+  fi
+fi
+
+# Set per-target output directory (using "host" if not cross-compiling)
+: ${CROSS:=host} ${OUTPUT:=$TOP/$CROSS}
+
+# Verify selected compiler works
+${CROSS_COMPILE}cc --static -xc - -o /dev/null <<< "int main(void){return 0;}"||
+  die "${CROSS_COMPILE}cc can't create static binaries"
+
+# ----- Create hermetic build environment
+
+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
+  # - cherry-picking specific commands from old path via symlink
+  if [ ! -e "$AIRLOCK/toybox" ]; then
+    announce "airlock" &&
+    PREFIX="$AIRLOCK" KCONFIG_CONFIG=.singleconfig_airlock CROSS_COMPILE= \
+      make clean defconfig toybox install_airlock && # see scripts/install.sh
+    rm .singleconfig_airlock || exit 1
+  fi
+  export PATH="$AIRLOCK"
+  CPIO_OPTS+=--no-preserve-owner
+fi
+
+# Create per-target work directories
+TEMP="$BUILD/${CROSS}-tmp" && rm -rf "$TEMP" &&
+mkdir -p "$TEMP" "$OUTPUT" "$LOG" || exit 1
+[ -z "$ROOT" ] && ROOT="$OUTPUT/fs" && rm -rf "$ROOT"
+
+# ----- log build output
+
+# Install command line recording wrapper, logs all commands run from $PATH
+if [ -z "$NOLOGPATH" ]; then
+  # Move cross compiler into $PATH so calls to it get logged
+  [ -n "$CROSS_COMPILE" ] && PATH="${CROSS_COMPILE%/*}:$PATH" &&
+    CROSS_COMPILE=${CROSS_COMPILE##*/}
+  export WRAPDIR="$BUILD/record-commands" LOGPATH="$LOG/$CROSS-commands.txt"
+  rm -rf "$WRAPDIR" "$LOGPATH" generated/obj &&
+  WRAPDIR="$WRAPDIR" CROSS_COMPILE= NOSTRIP=1 source mkroot/record-commands ||
+    exit 1
+fi
+
+# Start logging stdout/stderr
+rm -f "$LOG/$CROSS".{n,y} || exit 1
+[ -z "$NOLOG" ] && exec > >(tee "$LOG/$CROSS.n") 2>&1
+echo "Building for $CROSS"
+
+# ---------------------- Part 2: Create root filesystem -----------------------
+
+# ----- Create new root filesystem's directory layout.
+
+# FHS wants boot media opt srv usr/{local,share}, stuff under /var...
+mkdir -p "$ROOT"/{dev,etc/rc,home,mnt,proc,root,sys,tmp/run,usr/{bin,sbin,lib},var} &&
+chmod a+rwxt "$ROOT"/tmp && ln -s usr/{bin,sbin,lib} tmp/run "$ROOT" || exit 1
+
+# Write init script. Runs as pid 1 from initramfs to set up and hand off system.
+cat > "$ROOT"/init << 'EOF' &&
+#!/bin/sh
+
+export HOME=/home PATH=/bin:/sbin
+
+if ! mountpoint -q dev; then
+  mount -t devtmpfs dev dev
+  [ $$ -eq 1 ] && exec 0<>/dev/console 1>&0 2>&1
+  for i in ,fd /0,stdin /1,stdout /2,stderr
+  do ln -sf /proc/self/fd${i/,*/} dev/${i/*,/}; done
+  mkdir -p dev/shm
+  chmod +t /dev/shm
+fi
+mountpoint -q dev/pts || { mkdir -p dev/pts && mount -t devpts dev/pts dev/pts;}
+mountpoint -q proc || mount -t proc proc proc
+mountpoint -q sys || mount -t sysfs sys sys
+echo 0 99999 > /proc/sys/net/ipv4/ping_group_range
+
+if [ $$ -eq 1 ]; then # Setup networking for QEMU (needs /proc)
+  mountpoint -q mnt || [ -e /dev/?da ] && mount /dev/?da /mnt
+  ifconfig lo 127.0.0.1
+  ifconfig eth0 10.0.2.15
+  route add default gw 10.0.2.2
+  [ "$(date +%s)" -lt 1000 ] && timeout 2 sntp -sq 10.0.2.2 # Ask host
+  [ "$(date +%s)" -lt 10000000 ] && sntp -sq time.google.com
+
+  # Run package scripts (if any)
+  for i in $(ls -1 /etc/rc 2>/dev/null | sort); do . /etc/rc/"$i"; done
+
+  [ -z "$HANDOFF" ] && [ -e /mnt/init ] && HANDOFF=/mnt/init
+  [ -z "$HANDOFF" ] && HANDOFF=/bin/sh && echo -e '\e[?7hType exit when done.'
+  echo 3 > /proc/sys/kernel/printk
+  exec oneit $HANDOFF
+else # for chroot
+  /bin/sh
+  umount /dev/pts /dev /sys /proc
+fi
+EOF
+chmod +x "$ROOT"/init &&
+
+# Google's nameserver, passwd+group with special (root/nobody) accounts + guest
+echo "nameserver 8.8.8.8" > "$ROOT"/etc/resolv.conf &&
+cat > "$ROOT"/etc/passwd << 'EOF' &&
+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
+
+# Build any packages listed on command line
+for i in ${PKG:+plumbing $PKG}; do
+  pushd .
+  announce "$i"; PATH="$PKGDIR:$PATH" source $i || die $i
+  popd
+done
+
+# Build static toybox with existing .config if there is one, else defconfig+sh
+announce toybox
+[ -n "$PENDING" ] && rm -f .config
+[ -e .config ] && CONF=silentoldconfig || unset CONF
+for i in $PENDING sh route; do XX="$XX"$'\n'CONFIG_${i^^?}=y; done
+[ -e "$ROOT"/lib/libc.so ] || export LDFLAGS=--static
+PREFIX="$ROOT" make clean \
+  ${CONF:-defconfig KCONFIG_ALLCONFIG=<(echo "$XX")} toybox install || exit 1
+unset LDFLAGS
+
+# ------------------ Part 3: Build + package bootable system ------------------
+
+# Convert comma separated values in $1 to CONFIG=$2 lines
+csv2cfg() { sed -E '/^$/d;s/([^,]*)($|,)/CONFIG_\1='"$2"'\n/g' <<< "$1"; }
+
+# ----- Build kernel for target
+
+if [ -z "$LINUX" ] || [ ! -d "$LINUX/kernel" ]; then
+  echo 'No $LINUX directory, kernel build skipped.'
+else
+  # Which architecture are we building a kernel for?
+  LINUX="$(realpath "$LINUX")"
+  [ -z "$TARGET" ] &&
+    { [ "$CROSS" == host ] && TARGET="$(uname -m)" || TARGET="$CROSS"; }
+
+  # Target-specific info in an (alphabetical order) if/else staircase
+  # Each target needs board config, serial console, RTC, ethernet, block device.
+
+  if [ "$TARGET" == armv5l ]; 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
+    KERNEL_CONFIG="CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0"
+    DTB=arch/arm/boot/dts/versatile-pb.dtb
+  elif [ "$TARGET" == armv7l ] || [ "$TARGET" == aarch64 ]; then
+    if [ "$TARGET" == aarch64 ]; then
+      QEMU="aarch64 -M virt -cpu cortex-a57"
+      KARCH=arm64 VMLINUX=arch/arm64/boot/Image
+    else
+      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,NET_CORE,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
+  elif [ "$TARGET" == hexagon ]; then
+    QEMU="hexagon -M comet" KARGS=ttyS0 VMLINUX=vmlinux
+    KARCH="hexagon LLVM_IAS=1" KCONF=SPI,SPI_BITBANG,IOMMU_SUPPORT
+  elif [ "$TARGET" == i486 ] || [ "$TARGET" == i686 ] ||
+       [ "$TARGET" == x86_64 ] || [ "$TARGET" == x32 ]; then
+    if [ "$TARGET" == i486 ]; then
+      QEMU="i386 -cpu 486 -global fw_cfg.dma_enabled=false" KCONF=M486
+    elif [ "$TARGET" == i686 ]; then
+      QEMU="i386 -cpu pentium3" KCONF=MPENTIUMII
+    else
+      QEMU=x86_64 KCONF=64BIT
+      [ "$TARGET" == 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
+  elif [ "$TARGET" == 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_CORE,NET_VENDOR_NATSEMI,MACSONIC,SERIAL_PMACZILOG,SERIAL_PMACZILOG_TTYS,SERIAL_PMACZILOG_CONSOLE
+  elif [ "$TARGET" == mips ] || [ "$TARGET" == 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
+    [ "$TARGET" == mipsel ] && KCONF=$KCONF,CPU_LITTLE_ENDIAN &&
+      QEMU="mipsel -M malta"
+  elif [ "$TARGET" == 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
+  elif [ "$TARGET" == powerpc64 ] || [ "$TARGET" == 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
+    [ "$TARGET" == powerpc64le ] && KCONF=$KCONF,CPU_LITTLE_ENDIAN
+  elif [ "$TARGET" = s390x ]; then
+    QEMU="s390x" KARCH=s390 VMLINUX=arch/s390/boot/bzImage
+    KCONF=MARCH_Z900,PACK_STACK,NET_CORE,VIRTIO_NET,VIRTIO_BLK,SCLP_TTY,SCLP_CONSOLE,SCLP_VT220_TTY,SCLP_VT220_CONSOLE,S390_GUEST
+  elif [ "$TARGET" == sh2eb ]; then
+    BUILTIN=1 KARCH=sh VMLINUX=vmlinux
+    KERNEL_CONFIG=$'CONFIG_MEMORY_START=0x10000000\nCONFIG_CMDLINE="console=ttyUL0 earlycon"'
+    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
+  elif [ "$TARGET" == sh4 ]; then
+    QEMU="sh4 -M r2d -serial null -serial mon:stdio" KARCH=sh
+    KARGS="ttySC1 noiotrap" VMLINUX=arch/sh/boot/zImage
+    KERNEL_CONFIG="CONFIG_MEMORY_START=0x0c000000"
+    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
+#see also SPI SPI_SH_SCI MFD_SM501 RTC_CLASS RTC_DRV_R9701 RTC_DRV_SH RTC_HCTOSYS
+  else die "Unknown \$TARGET $TARGET"
+  fi
+
+  # Write the qemu launch script
+  if [ -n "$QEMU" ]; then
+    [ -z "$BUILTIN" ] && INITRD="-initrd initramfs.cpio.gz"
+    { echo qemu-system-"$QEMU" '"$@"' $QEMU_MORE -nographic -no-reboot -m 256 \
+        -kernel linux-kernel $INITRD ${DTB:+-dtb linux.dtb} \
+        "-append \"panic=1 HOST=$TARGET console=$KARGS \$KARGS\"" &&
+      echo "echo -e '\\e[?7h'"
+    } > "$OUTPUT"/run-qemu.sh &&
+    chmod +x "$OUTPUT"/run-qemu.sh || exit 1
+  fi
+
+  announce "linux-$KARCH"
+  pushd "$LINUX" && make distclean && popd &&
+  cp -sfR "$LINUX" "$TEMP/linux" && pushd "$TEMP/linux" &&
+
+  # Write linux-miniconfig
+  { 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,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,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 $KEXTRA ; do
+      echo "# architecture ${X:-independent}"
+      csv2cfg "$i" y
+      X=specific
+    done
+    [ -n "$BUILTIN" ] && echo -e CONFIG_INITRAMFS_SOURCE="\"$OUTPUT/fs\""
+    for i in $MODULES; do csv2cfg "$i" m; done
+    echo "$KERNEL_CONFIG"
+  } > "$OUTPUT/linux-miniconfig" &&
+  make ARCH=$KARCH allnoconfig KCONFIG_ALLCONFIG="$OUTPUT/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 &&
+  cp .config "$OUTPUT/linux-fullconfig" &&
+
+  # Build kernel. Copy config, device tree binary, and kernel binary to output
+  make ARCH=$KARCH CROSS_COMPILE="$CROSS_COMPILE" -j $(nproc) all || exit 1
+  [ -n "$DTB" ] && { cp "$DTB" "$OUTPUT/linux.dtb" || exit 1 ;}
+  if [ -n "$MODULES" ]; then
+    make ARCH=$KARCH INSTALL_MOD_PATH=modz modules_install &&
+      (cd modz && find lib/modules | cpio -o -H newc $CPIO_OPTS ) | gzip \
+       > "$OUTPUT/modules.cpio.gz" || exit 1
+  fi
+  cp "$VMLINUX" "$OUTPUT"/linux-kernel && cd .. && rm -rf linux && popd ||exit 1
+fi
+
+# clean up and package root filesystem for initramfs.
+if [ -z "$BUILTIN" ]; then
+  announce initramfs
+  { (cd "$ROOT" && find . | cpio -o -H newc $CPIO_OPTS ) || exit 1
+    ! test -e "$OUTPUT/modules.cpio.gz" || zcat $_;} | gzip \
+    > "$OUTPUT"/initramfs.cpio.gz || exit 1
+fi
+
+mv "$LOG/$CROSS".{n,y} && echo "Output is in $OUTPUT"
+rmdir "$TEMP" "$BUILD" 2>/dev/null || exit 0 # remove if empty, not an error
diff --git a/scripts/record-commands b/mkroot/record-commands
similarity index 100%
rename from scripts/record-commands
rename to mkroot/record-commands
diff --git a/scripts/root/dropbear b/mkroot/root/dropbear
similarity index 81%
rename from scripts/root/dropbear
rename to mkroot/root/dropbear
index 75839c3..9a4adcb 100755
--- a/scripts/root/dropbear
+++ b/mkroot/root/dropbear
@@ -1,4 +1,4 @@
-#!/bin/echo Try "scripts/mkroot.sh dropbear"
+#!/bin/echo Try "mkroot/mkroot.sh dropbear"
 
 # Example overlay file, adding dropbear (which requires zlib)
 
@@ -7,8 +7,8 @@
 download e6d119755acdf9104d7ba236b1242696940ed6dd \
   http://downloads.sf.net/libpng/zlib-1.2.11.tar.gz
 
-download c3d4fe27fa17ec8217dbedbd33dd73a1ca6cda2c \
-  https://matt.ucc.asn.au/dropbear/releases/dropbear-2020.81.tar.bz2
+download 9719ea91b5ce8d93ee9a50b5c3a5bcd628736181 \
+  https://matt.ucc.asn.au/dropbear/releases/dropbear-2022.82.tar.bz2
 
 echo === Native build static zlib
 
@@ -19,7 +19,6 @@
 make -j $(nproc) || exit 1
 
 # do _not_ cleanup zlib, we need the files we just built for dropbear
-cd ..
 
 echo === $HOST Native build static dropbear
 
@@ -27,7 +26,7 @@
 # Repeat after me: "autoconf is useless"
 echo 'echo "$@"' > config.sub &&
 ZLIB="$(echo ../zlib*)" &&
-CFLAGS="-I $ZLIB -O2" LDFLAGS="-L $ZLIB" ./configure --enable-static \
+CC="$CROSS_COMPILE"cc CFLAGS="-I $ZLIB -O2" LDFLAGS="-L $ZLIB" ./configure --enable-static \
   --disable-wtmp --host="$(basename "$CROSS_COMPILE" | sed 's/-$//')" &&
 sed -i 's@/usr/bin/dbclient@ssh@' options.h &&
 sed -i 's@\(#define NON_INETD_MODE\) 1@\1 0@' default_options.h &&
@@ -40,10 +39,12 @@
 do
   ln -s dropbearmulti $i || exit 1
 done
+# We didn't cleanup zlib
+unset ZLIB
+rm -rf ../zlib-*
+# cleanup dropbear
 cleanup
 
-rm -rf zlib-*
-
 # user root password root, user guest no password
 echo -e 'root:$1$939UTPzb$/PfVYAsF2Hqi/AQ3UBjbK/:::::::\nguest::::::::' > "$ROOT"/etc/shadow &&
 chmod 600 "$ROOT"/etc/shadow &&
@@ -55,4 +56,4 @@
 chmod +x "$OUTPUT"/ssh2dropbear.sh
 
 # Forward 127.0.0.1:2222 into qemu instance
-QEMU_MORE="-nic user,hostfwd=tcp:127.0.0.1:2222-:22"
+QEMU_MORE+=" -nic user,hostfwd=tcp:127.0.0.1:2222-:22"
diff --git a/mkroot/root/dynamic b/mkroot/root/dynamic
new file mode 100755
index 0000000..2ecfbda
--- /dev/null
+++ b/mkroot/root/dynamic
@@ -0,0 +1,15 @@
+#!/bin/echo Try "mkroot/mkroot.sh dynamic"
+
+# Copy dynamic libraries from cross compiler
+
+"${CROSS_COMPILE}cc" -xc - <<< 'void main(void) {;}' ||
+  die "${CROSS_COMPILE}cc can't create dynamic binaries"
+LDSO="$("${CROSS_COMPILE}readelf" -a a.out | sed -n 's/.*interpreter: \([^]]*\)[]]$/\1/p')"
+mkdir -p "$ROOT"/"$(dirname "$LDSO")" &&
+  cp "$LDSO" "$ROOT"/"$LDSO" || die "Couldn't copy ldso"
+unset LDSO
+
+"${CROSS_COMPILE}cc" -print-search-dirs | sed -n 's/libraries: =//p' | \
+  tr : '\n' | while read i; do
+    [ -e "$i" ] && find "$i" -maxdepth 1 -name '*.so' -o -name '*.so*[0-9]'
+  done | while read i; do cp -a "$i" "$ROOT"/lib/; done
diff --git a/mkroot/root/overlay b/mkroot/root/overlay
new file mode 100755
index 0000000..be0aaed
--- /dev/null
+++ b/mkroot/root/overlay
@@ -0,0 +1,3 @@
+#!/bin/echo Try "mkroot/mkroot.sh overlay"
+
+cp -a "${OVERLAY:=overlay}"/. "$ROOT"/.
diff --git a/scripts/root/plumbing b/mkroot/root/plumbing
similarity index 81%
rename from scripts/root/plumbing
rename to mkroot/root/plumbing
index ff30280..e72247c 100755
--- a/scripts/root/plumbing
+++ b/mkroot/root/plumbing
@@ -11,23 +11,23 @@
 # Grabs source from URL confirming SHA1 hash (Basically "wget $2")
 # If extracted source is in $DOWNLOAD (no version) build will use that instead
 download() {
-  FILE="$(basename "$2")"
+  local FILE="$(basename "$2")" WGET=wget
   [ -d "$DOWNLOAD/${FILE/-*/}" ] && echo "$FILE" local && return 0
   X=0; while true; do
     [ "$(sha1sum < "$DOWNLOAD/$FILE" 2>/dev/null)" == "$1  -" ] &&
       echo "$FILE" confirmed && break
     rm -f $DOWNLOAD/${FILE/-[0-9]*/}-[0-9]* || exit 1
-    [ $X -eq 0 ] && X=1 || exit 1
-    wget "$2" -O "$DOWNLOAD/$FILE"
+    [ $X -eq 0 ] && X=1 || [ $X -eq 1 ] && X=2 WGET=/usr/bin/wget || exit 1
+    $WGET "$2" -O "$DOWNLOAD/$FILE"
   done
 }
 
 # Usage: setupfor PACKAGE
 # Extracts source tarball (or snapshot a repo) to create disposable build dir.
-# Basically "tar xvzCf $MYBUILD $DOWNLOAD/$1.tar.gz && cd $NEWDIR"
+# Basically "tar -xvz -C $TEMP -f $DOWNLOAD/$1.tar.gz && cd $NEWDIR"
 setupfor() {
   PACKAGE="$(basename "$1")"
-  announce "$PACKAGE" && cd "$MYBUILD" && rm -rf "$PACKAGE" || exit 1
+  announce "$PACKAGE" && cd "$TEMP" && rm -rf "$PACKAGE" || exit 1
   if [ -d "$DOWNLOAD/$PACKAGE" ]; then
     cp -la "$DOWNLOAD/$PACKAGE/." "$PACKAGE" && cd "$PACKAGE" || exit 1
   else
diff --git a/mkroot/root/tests b/mkroot/root/tests
new file mode 100755
index 0000000..bca3b40
--- /dev/null
+++ b/mkroot/root/tests
@@ -0,0 +1,15 @@
+#!/bin/echo Try "mkroot/mkroot.sh $0"
+
+# Alas http://www.linux-usb.org/usb.ids is not versioned, so...
+download 36d4e16755502fbc684be75e56841e1014e4a94a \
+  https://github.com/usbids/usbids/raw/a5edeafb6099/usb.ids
+
+# Nor is https://pci-ids.ucw.cz/v2.2/pci.ids (tool version, not file version)
+download 6694284723e034f0c564e81a30879939d5ef8b7e \
+  https://github.com/pciutils/pciids/raw/c7929c0f9480/pci.ids
+
+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"
+MODULES+=FSCACHE,CACHEFILES
diff --git a/mkroot/testroot.sh b/mkroot/testroot.sh
new file mode 100755
index 0000000..0e3f449
--- /dev/null
+++ b/mkroot/testroot.sh
@@ -0,0 +1,99 @@
+#!/bin/bash
+
+# usage: mkroot/testroot.sh [TARGET...]
+#
+# Test system image(s) (by booting qemu with -hda test.img providing /mnt/init)
+# and check that:
+#
+# A) it boots and runs our code (which means /dev/hda works)
+# B) the clock is set sanely ("make" is unhappy when source newer than output)
+# C) it can talk to the virtual network
+#
+# Each successful test prints a === line, and all 3 means it passed.
+# Writes result into root/build/test/$TARGET-test.txt
+#
+# With arguments, tests those targets (verbosely). With no arguments, tests
+# each target with a linux-kernel (in parallel) and prints pass/fail summary.
+
+die() { echo "$@"; exit 1; }
+
+[ -n "$(which toybox)" -a -n "$(which mksquashfs)" ] ||
+  die "Need toybox and mksquashfs in $PATH"
+
+mkdir -p "${TEST:=$PWD/root/build/test}" &&
+
+# Setup test filesystem and package it into a squashfs.
+cat > "$TEST"/init << 'EOF' &&
+#!/bin/sh
+
+echo
+echo === init $HOST
+[ "$(date +%s)" -gt 1500000000 ] && echo === date ok $HOST
+wget http://10.0.2.2:65432 -O -
+# TODO: cd /mnt && scripts/test.sh
+EOF
+chmod +x "$TEST"/init &&
+
+mksquashfs "$TEST"/init configure scripts/ tests/ "$TEST"/init.sqf -noappend -all-root >/dev/null &&
+
+# Setup server on host's loopback for network smoke test
+echo === net ok > "$TEST"/index.html || die "smoketest setup"
+toybox netcat -p 65432 -s 127.0.0.1 -L toybox httpd "$TEST" &
+trap "kill $!" EXIT
+sleep .25
+
+[ -n "$(toybox wget http://127.0.0.1:65432/ -O - | grep ===)" ] || die "wget"
+
+do_test()
+{
+  X=$(dirname "$1") Y=$(basename $X)
+  [ ! -e "$1" ] && { echo skip "$Y"; return 0; }
+  # Alas KARGS=quiet doesn't silence qemu's bios, so filter output ourselves.
+  # QEMU broke -hda because too many people know how to use it, this is
+  # the new edgier version they added to be -hda without gratuitous breakage.
+  {
+    cd $X || continue
+    echo === $X
+    # Can't point two QEMU instances at same sqf because gratuitous file locking
+    cp "$TEST"/init.{sqf,$BASHPID} &&
+    # When stdin is a tty QEMU will SIGTTOU itself here, so </dev/null.
+    toybox timeout -i 10 bash -c "./run-qemu.sh -drive format=raw,file='$TEST'/init.$BASHPID < /dev/null 2>&1"
+    rm -f "$TEST/init.$BASHPID"
+    cd ../..
+  } | tee root/build/log/$Y-test.txt | { [ -z "$V" ] && cat >/dev/null || { [ "$V" -gt 1 ] && cat || grep '^=== '; } }
+}
+
+# Just test targets on command line?
+if [ $# -gt 0 ]; then
+  ((V++))
+  for I in "$@"; do do_test root/"$I"/linux-kernel; done
+  exit
+fi
+
+COUNT=0 CPUS=$(($(nproc)+0))
+for I in root/*/linux-kernel
+do
+  do_test "$I" | { [ -z "$V" ] && cat >/dev/null || { [ "$V" -gt 1 ] && cat || grep '^=== '; } } &
+  [ $((++COUNT)) -ge $CPUS ] &&
+    { wait -n; ((--COUNT)); [ -z "$V" ] && echo -n .; }
+done
+
+while [ $COUNT -gt 0 ]; do
+  wait -n; ((--COUNT)); [ -z "$V" ] && echo -n .
+done
+echo
+
+PASS= NOPASS=
+for I in root/*/linux-kernel
+do
+  [ ! -e "$I" ] && continue
+  X=$(dirname $I) Y=$(basename $X)
+
+  [ "$(grep '^=== ' root/build/log/$Y-test.txt | wc -l)" -eq 4 ] &&
+    PASS+="$Y " || NOPASS+="$Y "
+done
+
+[ -n "$PASS" ] && echo PASS=$PASS
+[ -n "$NOPASS" ] && echo NOPASS=$NOPASS
+X="$(ls root | egrep -xv "$(ls root/*/linux-kernel | sed 's@root/\([^/]*\)/linux-kernel@\1@' | tr '\n' '|')build" | xargs)"
+[ -n "$X" ] && echo No kernel: $X
diff --git a/post_update.sh b/post_update.sh
index 05c550c..39aefde 100755
--- a/post_update.sh
+++ b/post_update.sh
@@ -22,8 +22,12 @@
   mkdir -p $out
   for f in $files; do cp generated/$f $out/$f ; done
   rm -rf .config generated/
+
+  make allnoconfig KCONFIG_ALLCONFIG=.config-$which
 }
 
 generate "device"
 generate "linux"
 generate "mac"
+
+rm -rf .config
diff --git a/run-tests-on-android.sh b/run-tests-on-android.sh
index 89c8c91..d641b38 100755
--- a/run-tests-on-android.sh
+++ b/run-tests-on-android.sh
@@ -65,7 +65,11 @@
   elif [ "$non_toy" = "true" ]; then
     non_toy_failures="$non_toy_failures $toy"
   else
-    failures="$failures $toy"
+    if [[ "$toy" = "vi" ]]; then
+      non_toy_failures="$non_toy_failures $toy"
+    else
+      failures="$failures $toy"
+    fi
   fi
 }
 
diff --git a/scripts/change.sh b/scripts/change.sh
index 74889aa..dda5ee1 100755
--- a/scripts/change.sh
+++ b/scripts/change.sh
@@ -9,15 +9,11 @@
 export PREFIX=${PREFIX:-change/} &&
 mkdir -p "$PREFIX" || exit 1
 
-# Build all the commands standalone except:
-
-# sh - shell builtins like "cd" and "exit" need the multiplexer
-# help - needs to know what other commands are enabled (use command --help)
-
-for i in $("$UNSTRIPPED"/instlist | egrep -vw "sh|help")
+# Build all the commands standalone
+for i in $("$UNSTRIPPED"/instlist)
 do
   echo -n " $i" &&
-  scripts/single.sh $i > /dev/null 2>$PREFIX/${i}.bad &&
+  scripts/single.sh $i &>$PREFIX/${i}.bad &&
     rm $PREFIX/${i}.bad || echo -n '*'
 done
 echo
diff --git a/scripts/genconfig.sh b/scripts/genconfig.sh
index 034aa37..52a9c25 100755
--- a/scripts/genconfig.sh
+++ b/scripts/genconfig.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 
 # This has to be a separate file from scripts/make.sh so it can be called
-# before menuconfig.  (It's called again from scripts/make.sh just to be sure.)
+# before menuconfig. (It's called again from scripts/make.sh just to be sure.)
 
 source scripts/portability.sh
 
@@ -18,55 +18,11 @@
 {
   probecc "${@:2}" 2>/dev/null && DEFAULT=y || DEFAULT=n
   rm a.out 2>/dev/null
-  echo -e "config $1\n\tbool" || exit 1
-  echo -e "\tdefault $DEFAULT\n" || exit 1
+  echo -e "config $1\n\tbool\n\tdefault $DEFAULT\n" || exit 1
 }
 
 probeconfig()
 {
-  # Probe for container support on target
-  probesymbol TOYBOX_CONTAINER << EOF
-    #include <stdio.h>
-    #include <sys/syscall.h>
-    #include <linux/sched.h>
-    int x=CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET;
-
-    int main(int argc, char *argv[]){printf("%d", x+SYS_unshare+ SYS_setns);}
-EOF
-
-  probesymbol TOYBOX_FIFREEZE -c << EOF
-    #include <linux/fs.h>
-    #ifndef FIFREEZE
-    #error nope
-    #endif
-EOF
-
-  # Work around some uClibc limitations
-  probesymbol TOYBOX_ICONV -c << EOF
-    #include "iconv.h"
-EOF
-  
-  # Android and some other platforms miss utmpx
-  probesymbol TOYBOX_UTMPX -c << EOF
-    #include <utmpx.h>
-    #ifndef BOOT_TIME
-    #error nope
-    #endif
-    int main(int argc, char *argv[]) {
-      struct utmpx *a; 
-      if (0 != (a = getutxent())) return 0;
-      return 1;
-    }
-EOF
-
-  # Android is missing shadow.h
-  probesymbol TOYBOX_SHADOW -c << EOF
-    #include <shadow.h>
-    int main(int argc, char *argv[]) {
-      struct spwd *a = getspnam("root"); return 0;
-    }
-EOF
-
   # Some commands are android-specific
   probesymbol TOYBOX_ON_ANDROID -c << EOF
     #ifndef __ANDROID__
@@ -74,45 +30,12 @@
     #endif
 EOF
 
-  probesymbol TOYBOX_ANDROID_SCHEDPOLICY << EOF
-    #include <processgroup/sched_policy.h>
-
-    int main(int argc,char *argv[]) { get_sched_policy_name(0); }
-EOF
-
   # nommu support
   probesymbol TOYBOX_FORK << EOF
     #include <unistd.h>
     int main(int argc, char *argv[]) { return fork(); }
 EOF
   echo -e '\tdepends on !TOYBOX_FORCE_NOMMU'
-
-  probesymbol TOYBOX_PRLIMIT << EOF
-    #include <sys/types.h>
-    #include <sys/time.h>
-    #include <sys/resource.h>
-    int prlimit(pid_t pid, int resource, const struct rlimit *new_limit,
-      struct rlimit *old_limit);
-    int main(int argc, char *argv[]) { prlimit(0, 0, 0, 0); }
-EOF
-
-  probesymbol TOYBOX_GETRANDOM << EOF
-    #include <sys/random.h>
-    int main(void) { char buf[100]; getrandom(buf, 100, 0); }
-EOF
-
-  # glibc requires #define GNU to get the wrapper for this Linux system call,
-  # so just use syscall().
-  probesymbol TOYBOX_COPYFILERANGE << EOF
-    #include <sys/syscall.h>
-    #include <unistd.h>
-    int main(void) { syscall(__NR_copy_file_range, 0, 0, 1, 0, 123, 0); }
-EOF
-  probesymbol TOYBOX_HASTIMERS << EOF
-    #include <signal.h>
-    #include <time.h>
-    int main(void) {void *x=0;timer_create(CLOCK_MONOTONIC,x,x);}
-EOF
 }
 
 genconfig()
@@ -150,8 +73,7 @@
     $SED -En 's/([^:]*):.*(OLD|NEW)TOY\( *([a-zA-Z][^,]*) *,.*/\1:\3/p'
 }
 
-WORKING=
-PENDING=
+WORKING= PENDING= EXAMPLE=
 toys toys/*/*.c | (
 while IFS=":" read FILE NAME
 do
@@ -160,12 +82,13 @@
   [ "$NAME" == sh ] && FILE="toys/*/*.c"
   echo -e "$NAME: $FILE *.[ch] lib/*.[ch]\n\tscripts/single.sh $NAME\n"
   echo -e "test_$NAME:\n\tscripts/test.sh $NAME\n"
-  [ "${FILE/pending//}" != "$FILE" ] &&
-    PENDING="$PENDING $NAME" ||
+  [ "${FILE/example//}" != "$FILE" ] && EXAMPLE="$EXAMPLE $NAME" ||
+  [ "${FILE/pending//}" != "$FILE" ] && PENDING="$PENDING $NAME" ||
     WORKING="$WORKING $NAME"
 done &&
 echo -e "clean::\n\t@rm -f $WORKING $PENDING" &&
 echo -e "list:\n\t@echo $(echo $WORKING | tr ' ' '\n' | sort | xargs)" &&
-echo -e "list_pending:\n\t@echo $(echo $PENDING | tr ' ' '\n' | sort | xargs)" &&
+echo -e "list_example:\n\t@echo $(echo $EXAMPLE | tr ' ' '\n' | sort | xargs)"&&
+echo -e "list_pending:\n\t@echo $(echo $PENDING | tr ' ' '\n' | sort | xargs)"&&
 echo -e ".PHONY: $WORKING $PENDING" | $SED 's/ \([^ ]\)/ test_\1/g'
 ) > .singlemake
diff --git a/scripts/git-static-index.sh b/scripts/git-static-index.sh
new file mode 100755
index 0000000..fb9ac4e
--- /dev/null
+++ b/scripts/git-static-index.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# Create very basic index.html and commit links for a static git archive
+
+mkdir -p commit
+git log --pretty=%H | while read i
+do
+  [ -e commit/$i ] && break
+  git format-patch -1 --stdout $i > commit/$i
+  ln -sf $i commit/${i::12}
+done
+
+echo '<html><body><font face=monospace><table border=1 cellpadding=2>'
+echo '<tr valign=top><td>commit</td><td>author</td><td>date</td><td>description</td></tr>'
+git log --pretty='%H%n%an<%ae>%n%ad%n%s' --date=format:'%r<br />%d-%m-%Y' | while read HASH
+do
+  HASH="${HASH::12}"
+  read AUTHOR
+  AUTHOR1="${AUTHOR/<*/}"
+  AUTHOR1="${AUTHOR1::17}"
+  AUTHOR2="&lt;${AUTHOR/*</}"
+  AUTHOR2="${AUTHOR2::20}"
+  read DATE
+  DATE="${DATE/ /&nbsp;}"
+  read DESC
+  echo "<tr valign=top><td><a href=commit/$HASH>$HASH</a></td><td>$AUTHOR1<br />$AUTHOR2</td><td>$DATE</td><td>$DESC</td></tr>"
+done
+echo "</table></body></html>"
diff --git a/scripts/help.txt b/scripts/help.txt
index d369e47..feca0a8 100644
--- a/scripts/help.txt
+++ b/scripts/help.txt
@@ -1,6 +1,7 @@
   toybox          - Build toybox.
   COMMANDNAME     - Build individual toybox command as a standalone binary.
   list            - List COMMANDNAMEs you can build standalone.
+  list_example    - List example commands (often used by the test suite)
   list_pending    - List unfinished COMMANDNAMEs out of toys/pending.
   change          - Build each command standalone under change/.
   baseline        - Create toybox_old for use by bloatcheck.
@@ -22,6 +23,6 @@
                     LINUX= build kernel from this source, configured for qemu
   run_root        - boot toyroot under qemu, I.E. cd root/$CROSS && ./qemu-*.sh
 
-example: make defconfig toybox install CFLAGS="--static" CROSS_COMPILE=armv5l-
+example: make defconfig toybox install LDFLAGS="--static" CROSS_COMPILE=armv5l-
 or     : make root run_root CROSS=sh4 LINUX=~/linux
 
diff --git a/scripts/install.sh b/scripts/install.sh
index 842ff9b..38d9dce 100755
--- a/scripts/install.sh
+++ b/scripts/install.sh
@@ -31,7 +31,6 @@
 
 echo "Compile instlist..."
 
-NOBUILD=1 scripts/make.sh
 $DEBUG $HOSTCC -I . scripts/install.c -o "$UNSTRIPPED"/instlist || exit 1
 COMMANDS="$("$UNSTRIPPED"/instlist $LONG_PATH)"
 
@@ -106,11 +105,9 @@
 # The following are commands toybox should provide, but doesn't yet.
 # For now symlink the host version. This list must go away by 1.0.
 
-PENDING="dd diff expr git tr vi wget bash sh xzcat bc ar gzip   ftpd less awk unxz bison flex make nm"
-
-# "gcc" can go away if the kernel guys merge my patch:
-# http://lkml.iu.edu/hypermail/linux/kernel/2202.0/01505.html
-TOOLCHAIN="as cc ld gcc objdump"
+PENDING="expr git tr bash sh gzip   awk bison flex make"
+TOOLCHAIN="as cc ld objdump"
+TOOLCHAIN+="bc gcc" # both patched out but not in vanilla yet
 
 # Tools needed to build packages
 for i in $TOOLCHAIN $PENDING $HOST_EXTRA
diff --git a/scripts/make.sh b/scripts/make.sh
index b7bb693..9de7419 100755
--- a/scripts/make.sh
+++ b/scripts/make.sh
@@ -1,83 +1,105 @@
 #!/bin/bash
 
 # Grab default values for $CFLAGS and such.
-
 set -o pipefail
 source scripts/portability.sh
 
-# Default to running one more parallel cc instance than we have processors
-: ${CPUS:=$(($(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null)+1))}
+# Shell functions called by the build
+
+DASHN=-n
+true & wait -n 2>/dev/null || { wait; unset DASHN; }
+ratelimit()
+{
+  if [ "$#" -eq 0 ]
+  then
+    [ -z "$DASHN" ] && PIDS="$PIDS$! "
+    [ $((++COUNT)) -lt $CPUS ] && return 0
+  fi
+  ((--COUNT))
+  if [ -n "$DASHN" ]
+  then
+    wait -n
+    DONE=$(($DONE+$?))
+  else
+    # MacOS uses an ancient version of bash which hasn't got "wait -n", and
+    # wait without arguments always returns 0 instead of process exit code.
+    # This keeps $CPUS less busy when jobs finish out of order.
+    wait ${PIDS%% *}
+    DONE=$(($DONE+$?))
+    PIDS=${PIDS#* }
+  fi
+
+  return $DONE
+}
 
 # Respond to V= by echoing command lines as well as running them
-DOTPROG=
 do_loudly()
 {
-  [ ! -z "$V" ] && echo "$@" || echo -n "$DOTPROG"
+  { [ -n "$V" ] && echo "$@" || echo -n "$DOTPROG" ; } >&2
   "$@"
 }
 
-# Is anything under directory $2 newer than file $1
+# Is anything under directory $2 newer than generated/$1 (or does it not exist)?
 isnewer()
 {
-  CHECK="$1"
-  shift
-  [ ! -z "$(find "$@" -newer "$CHECK" 2>/dev/null || echo yes)" ]
+  [ -e "$GENDIR/$1" ] && [ -z "$(find "${@:2}" -newer "$GENDIR/$1")" ] &&
+    return 1
+  echo -n "${DIDNEWER:-$GENDIR/{}$1"
+  DIDNEWER=,
 }
 
-echo "Generate headers from toys/*/*.c..."
+# Build a tool that runs on the host
+hostcomp()
+{
+  if [ ! -f "$UNSTRIPPED"/$1 ] || [ "$UNSTRIPPED"/$1 -ot scripts/$1.c ]
+  then
+    do_loudly $HOSTCC scripts/$1.c -o "$UNSTRIPPED"/$1 || exit 1
+  fi
+}
 
-mkdir -p "$UNSTRIPPED"
+# Set/record build environment information
+compflags()
+{
+  [ -z "$VERSION" ] && [ -d ".git" ] && [ -n "$(which git 2>/dev/null)" ] &&
+   VERSION="-DTOYBOX_VERSION=\"$(git describe --tags --abbrev=12 2>/dev/null)\""
 
-if isnewer "$GENDIR"/Config.in toys || isnewer "$GENDIR"/Config.in Config.in
-then
-  echo "Extract configuration information from toys/*.c files..."
-  scripts/genconfig.sh
-fi
+  # VERSION and LIBRARIES volatile, changing either does not require a rebuild
+  echo '#!/bin/sh'
+  echo
+  echo "VERSION='$VERSION'"
+  echo "LIBRARIES='$(xargs 2>/dev/null < "$GENDIR/optlibs.dat")'"
+  echo "BUILD='${CROSS_COMPILE}${CC} $CFLAGS -I . $OPTIMIZE '\"\$VERSION\""
+  echo "LINK='$LDOPTIMIZE $LDFLAGS '\"\$LIBRARIES\""
+  echo "PATH='$PATH'"
+  echo "# Built from $KCONFIG_CONFIG"
+  echo
+}
 
-# Create a list of all the commands toybox can provide. Note that the first
-# entry is out of order on purpose (the toybox multiplexer command must be the
-# first element of the array). The rest must be sorted in alphabetical order
-# for fast binary search.
+# Make sure rm -rf isn't gonna go funny
+B="$(readlink -f "$PWD")/" A="$(readlink -f "$GENDIR")" A="${A%/}"/
+[ "$A" == "${B::${#A}}" ] &&
+  { echo "\$GENDIR=$GENDIR cannot include \$PWD=$PWD"; exit 1; }
+unset A B DOTPROG DIDNEWER
 
-if isnewer "$GENDIR"/newtoys.h toys
-then
-  echo -n "$GENDIR/newtoys.h "
-
-  echo "USE_TOYBOX(NEWTOY(toybox, NULL, TOYFLAG_STAYROOT|TOYFLAG_NOHELP))" \
-    > "$GENDIR"/newtoys.h
-  $SED -n -e 's/^USE_[A-Z0-9_]*(/&/p' toys/*/*.c \
-	| $SED 's/\(.*TOY(\)\([^,]*\),\(.*\)/\2 \1\2,\3/' | sort -s -k 1,1 \
-	| $SED 's/[^ ]* //'  >> "$GENDIR"/newtoys.h
-  [ $? -ne 0 ] && exit 1
-fi
-
-[ ! -z "$V" ] && echo "Which C files to build..."
+# Force full rebuild if our compiler/linker options changed
+cmp -s <(compflags|sed '5,8!d') <($SED '5,8!d' "$GENDIR"/build.sh 2>/dev/null)||
+  rm -rf "$GENDIR"/* # Keep symlink, delete contents
+mkdir -p "$UNSTRIPPED"  "$(dirname $OUTNAME)" || exit 1
 
 # Extract a list of toys/*/*.c files to compile from the data in $KCONFIG_CONFIG
 # (First command names, then filenames with relevant {NEW,OLD}TOY() macro.)
 
-[ -d ".git" ] && [ ! -z "$(which git 2>/dev/null)" ] &&
-   GITHASH="-DTOYBOX_VERSION=\"$(git describe --tags --abbrev=12 2>/dev/null)\""
+[ -n "$V" ] && echo -e "\nWhich C files to build..."
 TOYFILES="$($SED -n 's/^CONFIG_\([^=]*\)=.*/\1/p' "$KCONFIG_CONFIG" | xargs | tr ' [A-Z]' '|[a-z]')"
 TOYFILES="main.c $(egrep -l "TOY[(]($TOYFILES)[ ,]" toys/*/*.c | xargs)"
-BUILD="$(echo ${CROSS_COMPILE}${CC} $CFLAGS -I . $OPTIMIZE $GITHASH)"
 
 if [ "${TOYFILES/pending//}" != "$TOYFILES" ]
 then
   echo -e "\n\033[1;31mwarning: using unfinished code from toys/pending\033[0m"
 fi
 
-genbuildsh()
-{
-  # Write a canned build line for use on crippled build machines.
-
-  LLINK="$(echo $LDOPTIMIZE $LDFLAGS $(cat "$GENDIR"/optlibs.dat))"
-  echo -e "#!/bin/sh\n\nPATH='$PATH'\nBUILD='$BUILD'\nLINK='$LLINK'\n"
-  echo -e "\$BUILD lib/*.c $TOYFILES \$LINK -o $OUTNAME"
-}
-
-if ! cmp -s <(genbuildsh 2>/dev/null | head -n 5) \
-            <(head -n 5 "$GENDIR"/build.sh 2>/dev/null | $SED '5s/ -o .*//')
+# Probe library list if our compiler/linker options changed
+if [ ! -e "$GENDIR"/optlibs.dat ]
 then
   echo -n "Library probe"
 
@@ -85,25 +107,53 @@
   # compiler has no way to ignore a library that doesn't exist, so detect
   # and skip nonexistent libraries for it.
 
-  > "$GENDIR"/optlibs.dat
+  > "$GENDIR"/optlibs.new
+  [ -z "$V" ] && X=/dev/null || X=/dev/stderr
   for i in util crypt m resolv selinux smack attr crypto z log iconv tls ssl
   do
-    echo "int main(int argc, char *argv[]) {return 0;}" | \
-    ${CROSS_COMPILE}${CC} $CFLAGS $LDFLAGS -xc - -o "$GENDIR"/libprobe -l$i > /dev/null 2>/dev/null &&
-    echo -l$i >> "$GENDIR"/optlibs.dat
-    echo -n .
+    do_loudly ${CROSS_COMPILE}${CC} $CFLAGS $LDFLAGS -xc - -l$i >>$X 2>&1 \
+      -o "$UNSTRIPPED"/libprobe <<<"int main(int argc,char*argv[]){return 0;}"&&
+      do_loudly echo -n ' '-l$i >> "$GENDIR"/optlibs.new
   done
-  rm -f "$GENDIR"/libprobe
+  unset X
+  rm -f "$UNSTRIPPED"/libprobe
+  mv "$GENDIR"/optlibs.{new,dat} || exit 1
   echo
 fi
 
-genbuildsh > "$GENDIR"/build.sh && chmod +x "$GENDIR"/build.sh || exit 1
+# Write build variables (and set them locally), then append build invocation.
+compflags > "$GENDIR"/build.sh && source "$GENDIR/build.sh" &&
+  echo -e "\$BUILD lib/*.c $TOYFILES \$LINK -o $OUTNAME" >> "$GENDIR"/build.sh&&
+  chmod +x "$GENDIR"/build.sh || exit 1
+
+if isnewer Config.in toys || isnewer Config.in Config.in
+then
+  scripts/genconfig.sh
+fi
+
+# Does .config need dependency recalculation because toolchain changed?
+A="$($SED -n '/^config .*$/h;s/default \(.\)/\1/;T;H;g;s/config \([^\n]*\)[^yn]*\(.\)/\1=\2/p' "$GENDIR"/Config.probed | sort)"
+B="$(egrep "^CONFIG_($(echo "$A" | sed 's/=[yn]//' | xargs | tr ' ' '|'))=" "$KCONFIG_CONFIG" | $SED 's/^CONFIG_//' | sort)"
+A="$(echo "$A" | grep -v =n)"
+[ "$A" != "$B" ] &&
+  { echo -e "\nWarning: Config.probed changed, run 'make oldconfig'" >&2; }
+unset A B
+
+# Create a list of all the commands toybox can provide.
+if isnewer newtoys.h toys
+then
+  # The multiplexer is the first element in the array
+  echo "USE_TOYBOX(NEWTOY(toybox, 0, TOYFLAG_STAYROOT|TOYFLAG_NOHELP))" \
+    > "$GENDIR"/newtoys.h
+  # Sort rest by name for binary search (copy name to front, sort, remove copy)
+  $SED -n 's/^\(USE_[^(]*(.*TOY(\)\([^,]*\)\(,.*\)/\2 \1\2\3/p' toys/*/*.c \
+    | sort -s -k 1,1 | $SED 's/[^ ]* //'  >> "$GENDIR"/newtoys.h
+  [ $? -ne 0 ] && exit 1
+fi
 
 #TODO: "make $SED && make" doesn't regenerate config.h because diff .config
-if true #isnewer "$GENDIR"/config.h "$KCONFIG_CONFIG"
+if true #isnewer config.h "$KCONFIG_CONFIG"
 then
-  echo "Make $GENDIR/config.h from $KCONFIG_CONFIG."
-
   # This long and roundabout sed invocation is to make old versions of sed
   # happy. New ones have '\n' so can replace one line with two without all
   # the branches and tedious mucking about with hyperspace.
@@ -130,20 +180,14 @@
     $KCONFIG_CONFIG > "$GENDIR"/config.h || exit 1
 fi
 
-if [ ! -f "$GENDIR"/mkflags ] || [ "$GENDIR"/mkflags -ot scripts/mkflags.c ]
-then
-  do_loudly $HOSTCC scripts/mkflags.c -o "$UNSTRIPPED"/mkflags || exit 1
-fi
-
 # 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
 # allow multiple NEWTOY() in the same C file. (When disabled the FLAG is 0,
 # so flags&0 becomes a constant 0 allowing dead code elimination.)
 
-if isnewer "$GENDIR"/flags.h toys "$KCONFIG_CONFIG"
+hostcomp mkflags
+if isnewer flags.h toys "$KCONFIG_CONFIG"
 then
-  echo -n "$GENDIR/flags.h "
-
   # Parse files through C preprocessor twice, once to get flags for current
   # .config and once to get flags for allyesconfig
   for I in A B
@@ -187,18 +231,16 @@
 {
   for i in toys/*/*.c
   do
-    # alas basename -s isn't in posix yet.
-    NAME="$(echo $i | $SED 's@.*/\(.*\)\.c@\1@')"
+    NAME=${i##*/} NAME=${NAME%\.c}
     DATA="$($SED -n -e '/^GLOBALS(/,/^)/b got;b;:got' \
             -e 's/^GLOBALS(/_data {/' \
             -e 's/^)/};/' -e 'p' $i)"
-    [ ! -z "$DATA" ] && echo -e "// $i\n\nstruct $NAME$DATA\n"
+    [ -n "$DATA" ] && echo -e "// $i\n\nstruct $NAME$DATA\n"
   done
 }
 
-if isnewer "$GENDIR"/globals.h toys
+if isnewer globals.h toys
 then
-  echo -n "$GENDIR/globals.h "
   GLOBSTRUCT="$(getglobals)"
   (
     echo "$GLOBSTRUCT"
@@ -210,53 +252,40 @@
   ) > "$GENDIR"/globals.h
 fi
 
-if [ ! -f "$UNSTRIPPED"/mktags ] || [ "$UNSTRIPPED"/mktags -ot scripts/mktags.c ]
+hostcomp mktags
+if isnewer tags.h toys
 then
-  do_loudly $HOSTCC scripts/mktags.c -o "$UNSTRIPPED"/mktags || exit 1
-fi
-
-if isnewer "$GENDIR"/tags.h toys
-then
-  echo -n "$GENDIR/tags.h "
-
   $SED -n '/TAGGED_ARRAY(/,/^)/{s/.*TAGGED_ARRAY[(]\([^,]*\),/\1/;p}' \
     toys/*/*.c lib/*.c | "$UNSTRIPPED"/mktags > "$GENDIR"/tags.h
 fi
 
-if [ ! -f "$UNSTRIPPED"/config2help ] || [ "$UNSTRIPPED"/config2help -ot scripts/config2help.c ]
+hostcomp config2help
+if isnewer help.h "$GENDIR"/Config.in
 then
-  do_loudly $HOSTCC scripts/config2help.c -o "$UNSTRIPPED"/config2help || exit 1
-fi
-if isnewer "$GENDIR"/help.h "$GENDIR"/Config.in
-then
-  echo "$GENDIR/help.h"
   "$UNSTRIPPED"/config2help Config.in $KCONFIG_CONFIG > "$GENDIR"/help.h || exit 1
 fi
+[ -z "$DIDNEWER" ] || echo }
 
-[ ! -z "$NOBUILD" ] && exit 0
+[ -n "$NOBUILD" ] && exit 0
 
-echo -n "Compile $OUTNAME"
-[ ! -z "$V" ] && echo
+echo "Compile $OUTNAME"
 DOTPROG=.
 
-# This is a parallel version of: do_loudly $BUILD $FILES $LLINK || exit 1
+# This is a parallel version of: do_loudly $BUILD lib/*.c $TOYFILES $LINK
 
-# Any headers newer than the oldest generated/obj file?
+# Build all if oldest generated/obj file isn't newer than all header files.
 X="$(ls -1t "$GENDIR"/obj/* 2>/dev/null | tail -n 1)"
-# TODO: redo this
-if [ ! -e "$X" ] || [ ! -z "$(find toys -name "*.h" -newer "$X")" ]
+if [ ! -e "$X" ] || [ -n "$(find toys -name "*.h" -newer "$X")" ]
 then
   rm -rf "$GENDIR"/obj && mkdir -p "$GENDIR"/obj || exit 1
 else
+  # always redo toy_list[] and help_data[]
   rm -f "$GENDIR"/obj/main.o || exit 1
 fi
 
 # build each generated/obj/*.o file in parallel
 
-unset PENDING LNKFILES CLICK
-DONE=0
-COUNT=0
-
+PENDING= LNKFILES= CLICK= DONE=0 COUNT=0
 for i in lib/*.c click $TOYFILES
 do
   [ "$i" == click ] && CLICK=1 && continue
@@ -266,30 +295,25 @@
   OUT="$GENDIR/obj/${X%%.c}.o"
   LNKFILES="$LNKFILES $OUT"
 
-  # Library files don't need to be rebuilt if older than .config.
-  # ($TOYFILES contents can depend on CONFIG symbols, lib/*.c never should.)
-
+  # Library files don't get rebuilt if older than .config, but commands do.
   [ "$OUT" -nt "$i" ] && [ -z "$CLICK" -o "$OUT" -nt "$KCONFIG_CONFIG" ] &&
     continue
 
   do_loudly $BUILD -c $i -o $OUT &
 
-  # ratelimit to $CPUS many parallel jobs, detecting errors
-  [ $((++COUNT)) -ge $CPUS ] && { wait $DASHN; DONE=$?; : $((--COUNT)); }
-  [ $DONE -ne 0 ] && break
+  ratelimit || break
 done
-# wait for all background jobs, detecting errors
 
-while [ $((COUNT--)) -gt 0 ]
+# wait for all background jobs, detecting errors
+while [ "$COUNT" -gt 0 ]
 do
-  wait $DASHN;
-  DONE=$((DONE+$?))
+  ratelimit done
 done
 [ $DONE -ne 0 ] && exit 1
 
 UNSTRIPPED="$UNSTRIPPED/${OUTNAME/*\//}"
-do_loudly $BUILD $LNKFILES $LLINK -o "$UNSTRIPPED" || exit 1
-if [ ! -z "$NOSTRIP" ] ||
+do_loudly $BUILD $LNKFILES $LINK -o "$UNSTRIPPED" || exit 1
+if [ -n "$NOSTRIP" ] ||
   ! do_loudly ${CROSS_COMPILE}${STRIP} "$UNSTRIPPED" -o "$OUTNAME"
 then
   [ -z "$NOSTRIP" ] && echo "strip failed, using unstripped"
@@ -297,10 +321,9 @@
   cp "$UNSTRIPPED" "$OUTNAME" || exit 1
 fi
 
-# gcc 4.4's strip command is buggy, and doesn't set the executable bit on
-# its output the way SUSv4 suggests it do so. While we're at it, make sure
-# we don't have the "w" bit set so things like bzip2's "cp -f" install don't
-# overwrite our binary through the symlink.
+# Remove write bit set so buggy installs (like bzip's) don't overwrite the
+# multiplexer binary via truncate-and-write through a symlink.
 do_loudly chmod 555 "$OUTNAME" || exit 1
 
-echo
+# Ensure make wrapper sees success return code
+[ -z "$V" ] && echo >&2 || true
diff --git a/scripts/mcm-buildall.sh b/scripts/mcm-buildall.sh
index cac4137..11a1013 100755
--- a/scripts/mcm-buildall.sh
+++ b/scripts/mcm-buildall.sh
@@ -91,7 +91,11 @@
 
   # Prevent cross compiler reusing dynamically linked host build files for
   # $BOOTSTRAP arch
-  [ -z "$TYPE" ] && make clean
+  [ -z "$TYPE" ] && {
+    [ -e musl-git-master ] && mv musl-git-master keep-this-dir
+    make clean
+    [ -e keep-this-dir ] && mv keep-this-dir musl-git-master
+  }
 
   if [ "$TYPE" == native ]
   then
@@ -138,13 +142,6 @@
   PP=patches/musl-"$(sed -n 's/MUSL_VER[ \t]*=[ \t]*//p' Makefile)"
   mkdir -p "$PP" &&
   cat > "$PP"/0001-nommu.patch << 'EOF'
---- a/include/features.h
-+++ b/include/features.h
-@@ -3,2 +3,4 @@
- 
-+#define __MUSL__ 1
-+
- #if defined(_ALL_SOURCE) && !defined(_GNU_SOURCE)
 --- a/src/legacy/daemon.c
 +++ b/src/legacy/daemon.c
 @@ -17,3 +17,3 @@
diff --git a/scripts/mkflags.c b/scripts/mkflags.c
index 6560db5..79cf165 100644
--- a/scripts/mkflags.c
+++ b/scripts/mkflags.c
@@ -1,5 +1,5 @@
-// Take three word input lines on stdin and produce flag #defines to stdout.
-// The three words on each input lnie are command name, option string with
+// Read three word input lines from stdin and produce flag #defines to stdout.
+// The three words on each input line are command name, option string with
 // current config, option string from allyesconfig. The three are space
 // separated and the last two are in double quotes.
 
@@ -14,9 +14,8 @@
 #include <ctype.h>
 
 struct flag {
-  struct flag *next;
+  struct flag *next, *lopt;
   char *command;
-  struct flag *lopt;
 };
 
 int chrtype(char c)
@@ -38,7 +37,7 @@
 char *mark_gaps(char *flags, char *all)
 {
   char *n, *new, c;
-  int bare = 2;
+  int bare = 1;
 
   // Shell feeds in " " for blank args, leading space not meaningful.
   while (isspace(*flags)) flags++;
@@ -50,7 +49,6 @@
     if (*all == '(') {
       int len = 0;
 
-      if (bare) bare = 1;
       while (all[len]) if (all[len++] == ')') break;
       if (strncmp(flags, all, len)) {
         // bare longopts need their own skip placeholders
@@ -95,6 +93,10 @@
     if (*string == '(') {
       struct flag *new = calloc(sizeof(struct flag), 1);
 
+      if (string[1]==')') {
+        fprintf(stderr, "empty () longopt in '%s'", err);
+        exit(1);
+      }
       new->command = ++string;
 
       // Attach longopt to previous short opt, if any.
@@ -131,6 +133,10 @@
     } else {
       struct flag *new = calloc(sizeof(struct flag), 1);
 
+      if (string[0]=='~' && string[1]!='(') {
+        fprintf(stderr, "~ without (longopt) in '%s'", err);
+        exit(1);
+      }
       new->command = string++;
       new->next = list;
       list = new;
@@ -164,9 +170,8 @@
   // See "intentionally crappy", above.
   if (!(out = outbuf)) return 1;
 
-  printf("#undef FORCED_FLAG\n#undef FORCED_FLAGLL\n"
-    "#ifdef FORCE_FLAGS\n#define FORCED_FLAG 1\n#define FORCED_FLAGLL 1ULL\n"
-    "#else\n#define FORCED_FLAG 0\n#define FORCED_FLAGLL 0LL\n#endif\n\n");
+  printf("#undef FORCED_FLAG\n#ifdef FORCE_FLAGS\n#define FORCED_FLAG 1LL\n"
+    "#else\n#define FORCED_FLAG 0LL\n#endif\n\n");
 
   for (;;) {
     struct flag *flist, *aflist, *offlist;
@@ -208,7 +213,8 @@
     while (offlist) {
       char *s = (char []){0, 0, 0, 0};
 
-      if (!offlist->command) s = offlist->lopt->command;
+      if (!offlist->command || *offlist->command=='~')
+        s = offlist->lopt->command;
       else {
         *s = *offlist->command;
         if (127 < (unsigned char)*s) sprintf(s, "X%02X", 127&*s);
@@ -223,11 +229,11 @@
     out += strlen(out);
 
     while (aflist) {
-      char *llstr = bit>30 ? "LL" : "", *s = (char []){0, 0, 0, 0};
+      char *s = (char []){0, 0, 0, 0};
       int enabled = 0;
 
       // Output flag macro for bare longopts
-      if (!aflist->command) {
+      if (!aflist->command || *aflist->command=='~') {
         s = aflist->lopt->command;
         if (flist && flist->lopt &&
             !strcmp(flist->lopt->command, aflist->lopt->command)) enabled++;
@@ -238,8 +244,8 @@
         if (flist && flist->command && *aflist->command == *flist->command)
           enabled++;
       }
-      out += sprintf(out, "#define FLAG_%s (%s%s<<%d)\n",
-                       s, enabled ? "1" : "FORCED_FLAG", llstr, bit++);
+      out += sprintf(out, "#define FLAG_%s (%s<<%d)\n",
+                       s, enabled ? "1LL" : "FORCED_FLAG", bit++);
       aflist = aflist->next;
       if (enabled) flist = flist->next;
     }
diff --git a/scripts/mkroot.sh b/scripts/mkroot.sh
index c099bec..2ac634b 100755
--- a/scripts/mkroot.sh
+++ b/scripts/mkroot.sh
@@ -1,292 +1 @@
-#!/bin/bash
-
-# ------------------------------ Part 1: Setup -------------------------------
-
-# Clear environment variables by restarting script w/bare minimum passed through
-[ -z "$NOCLEAR" ] && exec env -i NOCLEAR=1 HOME="$HOME" PATH="$PATH" \
-    LINUX="$LINUX" CROSS="$CROSS" CROSS_COMPILE="$CROSS_COMPILE" "$0" "$@"
-
-# assign command line NAME=VALUE args to env vars, the rest are packages
-for i in "$@"; do
-  [ "${i/=/}" != "$i" ] && export "$i" || { [ "$i" != -- ] && PKG="$PKG $i"; }
-done
-
-# Set default directory locations (overrideable from command line)
-: ${LOG:=${BUILD:=${TOP:=$PWD/root}/build}/log} ${AIRLOCK:=$BUILD/airlock}
-: ${CCC:=$PWD/ccc} ${PKGDIR:=$PWD/scripts/root}
-
-# useful functions
-announce() { echo -e "\033]2;$CROSS $*\007\n=== $*"; }
-die() { echo "$@" >&2; exit 1; }
-
-# ----- Are we cross compiling (via CROSS_COMPILE= or CROSS=)
-
-if [ -n "$CROSS_COMPILE" ]; then
-  CROSS_COMPILE="$(realpath -s "$CROSS_COMPILE")" # airlock needs absolute path
-  [ -z "$CROSS" ] && CROSS=${CROSS_COMPILE/*\//} CROSS=${CROSS/-*/}
-
-elif [ -n "$CROSS" ]; then # CROSS=all/allnonstop/$ARCH else list known $ARCHes
-  [ ! -d "$CCC" ] && die "No ccc symlink to compiler directory."
-  TARGETS="$(ls "$CCC" | sed -n 's/-.*//p' | sort -u)"
-
-  if [ "${CROSS::3}" == all ]; then # loop calling ourselves for each target
-    for i in $TARGETS; do
-      "$0" "$@" CROSS=$i || [ "$CROSS" == allnonstop ] || exit 1
-    done; exit
-
-  else # Find matching cross compiler under ccc/ else list available targets
-    CROSS_COMPILE="$(echo "$CCC/$CROSS"-*cross/bin/"$CROSS"*-cc)" # wildcard
-    [ ! -e "$CROSS_COMPILE" ] && echo $TARGETS && exit # list available targets
-    CROSS_COMPILE="${CROSS_COMPILE%cc}" # trim to prefix for cc/ld/as/nm/strip
-  fi
-fi
-
-# Verify selected compiler works
-${CROSS_COMPILE}cc --static -xc - -o /dev/null <<< "int main(void){return 0;}"||
-  die "${CROSS_COMPILE}cc can't create static binaries"
-
-# When not cross compiling set CROSS=host. Create per-target output directory
-: ${CROSS:=host} ${OUTPUT:=$TOP/$CROSS}
-
-# ----- Create hermetic build environment
-
-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
-  # - cherry-picking specific commands from old path via symlink
-  if [ ! -e "$AIRLOCK/toybox" ]; then
-    announce "airlock" &&
-    PREFIX="$AIRLOCK" KCONFIG_CONFIG=.singleconfig_airlock CROSS_COMPILE= \
-      make clean defconfig toybox install_airlock && # see scripts/install.sh
-    rm .singleconfig_airlock || exit 1
-  fi
-  export PATH="$AIRLOCK"
-fi
-
-# Create per-target work directories
-MYBUILD="$BUILD/${CROSS}-tmp" && rm -rf "$MYBUILD" &&
-mkdir -p "$MYBUILD" "$OUTPUT" "$LOG" || exit 1
-[ -z "$ROOT" ] && ROOT="$OUTPUT/fs" && rm -rf "$ROOT"
-
-# ----- log build output
-
-# Install command line recording wrapper, logs all commands run from $PATH
-if [ -z "$NOLOGPATH" ]; then
-  # Move cross compiler into $PATH so calls to it get logged
-  [ -n "$CROSS_COMPILE" ] && PATH="${CROSS_COMPILE%/*}:$PATH" &&
-    CROSS_COMPILE=${CROSS_COMPILE##*/}
-  export WRAPDIR="$BUILD/record-commands" LOGPATH="$LOG/$CROSS-commands.txt"
-  rm -rf "$WRAPDIR" "$LOGPATH" generated/obj &&
-  WRAPDIR="$WRAPDIR" CROSS_COMPILE= NOSTRIP=1 source scripts/record-commands ||
-    exit 1
-fi
-
-# Start logging stdout/stderr
-rm -f "$LOG/$CROSS".{n,y} || exit 1
-[ -z "$NOLOG" ] && exec > >(tee "$LOG/$CROSS.n") 2>&1
-echo "Building for $CROSS"
-
-# ---------------------- Part 2: Create root filesystem -----------------------
-
-# ----- Create new root filesystem's directory layout.
-
-# FHS wants boot media opt srv usr/{local,share}, stuff under /var...
-mkdir -p "$ROOT"/{dev,etc/rc,home,mnt,proc,root,sys,tmp/run,usr/{bin,sbin,lib},var} &&
-chmod a+rwxt "$ROOT"/tmp && ln -s usr/{bin,sbin,lib} tmp/run "$ROOT" || exit 1
-
-# Write init script. Runs as pid 1 from initramfs to set up and hand off system.
-cat > "$ROOT"/init << 'EOF' &&
-#!/bin/sh
-
-export HOME=/home PATH=/bin:/sbin
-
-if ! mountpoint -q dev; then
-  mount -t devtmpfs dev dev
-  [ $$ -eq 1 ] && exec 0<>/dev/console 1>&0 2>&1
-  for i in ,fd /0,stdin /1,stdout /2,stderr
-  do ln -sf /proc/self/fd${i/,*/} dev/${i/*,/}; done
-  mkdir dev/shm
-  chmod +t /dev/shm
-fi
-mountpoint -q dev/pts || { mkdir dev/pts && mount -t devpts dev/pts dev/pts; }
-mountpoint -q proc || mount -t proc proc proc
-mountpoint -q sys || mount -t sysfs sys sys
-echo 0 99999 > /proc/sys/net/ipv4/ping_group_range
-
-if [ $$ -eq 1 ]; then # Setup networking for QEMU (needs /proc)
-  ifconfig lo 127.0.0.1
-  ifconfig eth0 10.0.2.15
-  route add default gw 10.0.2.2
-  [ "$(date +%s)" -lt 1000 ] && timeout 2 sntp -sq 10.0.2.2 # Ask host
-  [ "$(date +%s)" -lt 10000000 ] && sntp -sq time.google.com
-
-  # Run package scripts (if any)
-  for i in $(ls -1 /etc/rc 2>/dev/null | sort); do . /etc/rc/"$i"; done
-
-  [ -z "$CONSOLE" ] && CONSOLE="$(</sys/class/tty/console/active)"
-  [ -z "$HANDOFF" ] && HANDOFF=/bin/sh && echo -e '\e[?7hType exit when done.'
-  echo 3 > /proc/sys/kernel/printk
-  exec oneit -c /dev/"${CONSOLE:-console}" $HANDOFF
-else # for chroot
-  /bin/sh
-  umount /dev/pts /dev /sys /proc
-fi
-EOF
-chmod +x "$ROOT"/init &&
-
-# Google's nameserver, passwd+group with special (root/nobody) accounts + guest
-echo "nameserver 8.8.8.8" > "$ROOT"/etc/resolv.conf &&
-cat > "$ROOT"/etc/passwd << 'EOF' &&
-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
-
-# Build static toybox with existing .config if there is one, else defconfig+sh
-announce toybox
-[ ! -z "$PENDING" ] && rm -f .config
-[ -e .config ] && CONF=silentoldconfig || unset CONF
-for i in $PENDING sh route wget; do XX="$XX"$'\n'CONFIG_${i^^?}=y; done
-LDFLAGS=--static PREFIX="$ROOT" make clean \
-  ${CONF:-defconfig KCONFIG_ALLCONFIG=<(echo "$XX")} toybox install || exit 1
-
-# Build any packages listed on command line
-for i in ${PKG:+plumbing $PKG}; do
-  announce "$i"; PATH="$PKGDIR:$PATH" source $i || die $i
-done
-
-# ------------------ Part 3: Build + package bootable system ------------------
-
-# ----- Build kernel for target
-
-if [ -z "$LINUX" ] || [ ! -d "$LINUX/kernel" ]; then
-  echo 'No $LINUX directory, kernel build skipped.'
-else
-  # Which architecture are we building a kernel for?
-  LINUX="$(realpath "$LINUX")"
-  [ -z "$TARGET" ] &&
-    { [ "$CROSS" == host ] && TARGET="$(uname -m)" || TARGET="$CROSS"; }
-
-  # Target-specific info in an (alphabetical order) if/else staircase
-  # Each target needs board config, serial console, RTC, ethernet, block device.
-
-  if [ "$TARGET" == armv5l ]; 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
-    KERNEL_CONFIG="CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0"
-    DTB=arch/arm/boot/dts/versatile-pb.dtb
-  elif [ "$TARGET" == armv7l ] || [ "$TARGET" == aarch64 ]; then
-    if [ "$TARGET" == aarch64 ]; then
-      QEMU="aarch64 -M virt -cpu cortex-a57"
-      KARCH=arm64 VMLINUX=arch/arm64/boot/Image
-    else
-      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,NET_CORE,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,CONFIG_ARM_LPAE
-  elif [ "$TARGET" == hexagon ]; then
-    QEMU="hexagon -M comet" KARGS=ttyS0 VMLINUX=vmlinux
-    KARCH="hexagon LLVM_IAS=1" KCONF=SPI,SPI_BITBANG,IOMMU_SUPPORT
-  elif [ "$TARGET" == i486 ] || [ "$TARGET" == i686 ] ||
-       [ "$TARGET" == x86_64 ] || [ "$TARGET" == x32 ]; then
-    if [ "$TARGET" == i486 ]; then
-      QEMU="i386 -cpu 486 -global fw_cfg.dma_enabled=false" KCONF=M486
-    elif [ "$TARGET" == i686 ]; then
-      QEMU="i386 -cpu pentium3" KCONF=MPENTIUMII
-    else
-      QEMU=x86_64 KCONF=64BIT
-      [ "$TARGET" == 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
-  elif [ "$TARGET" == m68k ]; then
-    QEMU="m68k -M q800" KARCH=m68k KARGS=ttyS0 VMLINUX=vmlinux
-    KCONF=MMU,M68040,M68KFPU_EMU,MAC,SCSI_MAC_ESP,MACINTOSH_DRIVERS,ADB,ADB_MACII,NET_CORE,NET_VENDOR_NATSEMI,MACSONIC,SERIAL_PMACZILOG,SERIAL_PMACZILOG_TTYS,SERIAL_PMACZILOG_CONSOLE
-  elif [ "$TARGET" == mips ] || [ "$TARGET" == 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
-    [ "$TARGET" == mipsel ] && KCONF=$KCONF,CPU_LITTLE_ENDIAN &&
-      QEMU="mipsel -M malta"
-  elif [ "$TARGET" == powerpc ]; then
-    KARCH=powerpc QEMU="ppc -M g3beige" KARGS=ttyS0 VMLINUX=vmlinux
-    KCONF=ALTIVEC,PPC_PMAC,PPC_OF_BOOT_TRAMPOLINE,IDE,IDE_GD,IDE_GD_ATA,BLK_DEV_IDE_PMAC,BLK_DEV_IDE_PMAC_ATA100FIRST,MACINTOSH_DRIVERS,ADB,ADB_CUDA,NET_VENDOR_NATSEMI,NET_VENDOR_8390,NE2K_PCI,SERIO,SERIAL_PMACZILOG,SERIAL_PMACZILOG_TTYS,SERIAL_PMACZILOG_CONSOLE,BOOTX_TEXT
-  elif [ "$TARGET" == powerpc64le ]; then
-    KARCH=powerpc QEMU="ppc64 -M pseries -vga none" KARGS=hvc0
-    VMLINUX=vmlinux
-    KCONF=PPC64,PPC_PSERIES,CPU_LITTLE_ENDIAN,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
-  elif [ "$TARGET" = s390x ]; then
-    QEMU="s390x" KARCH=s390 VMLINUX=arch/s390/boot/bzImage
-    KCONF=MARCH_Z900,PACK_STACK,NET_CORE,VIRTIO_NET,VIRTIO_BLK,SCLP_TTY,SCLP_CONSOLE,SCLP_VT220_TTY,SCLP_VT220_CONSOLE,S390_GUEST
-  elif [ "$TARGET" == sh2eb ]; then
-    BUILTIN=1 KARCH=sh VMLINUX=vmlinux
-    KERNEL_CONFIG=$'CONFIG_MEMORY_START=0x10000000\nCONFIG_CMDLINE="console=ttyUL0 earlycon"'
-    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
-  elif [ "$TARGET" == sh4 ]; then
-    QEMU="sh4 -M r2d -serial null -serial mon:stdio" KARCH=sh
-    KARGS="ttySC1 noiotrap" VMLINUX=arch/sh/boot/zImage
-    KERNEL_CONFIG="CONFIG_MEMORY_START=0x0c000000"
-    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
-#see also SPI SPI_SH_SCI MFD_SM501 RTC_CLASS RTC_DRV_R9701 RTC_DRV_SH RTC_HCTOSYS
-  else die "Unknown \$TARGET $TARGET"
-  fi
-
-  # Write the qemu launch script
-  if [ -n "$QEMU" ]; then
-    [ -z "$BUILTIN" ] && INITRD="-initrd ${CROSS}root.cpio.gz"
-    { echo qemu-system-"$QEMU" '"$@"' $QEMU_MORE -nographic -no-reboot -m 256 \
-        -kernel $(basename $VMLINUX) $INITRD ${DTB:+-dtb "$(basename "$DTB")"} \
-        "-append \"panic=1 HOST=$TARGET console=$KARGS \$KARGS\"" &&
-      echo "echo -e '\\e[?7h'"
-    } > "$OUTPUT/qemu-$TARGET.sh" &&
-    chmod +x "$OUTPUT/qemu-$TARGET.sh" || exit 1
-  fi
-
-  announce "linux-$KARCH"
-  pushd "$LINUX" && make distclean && popd &&
-  cp -sfR "$LINUX" "$MYBUILD/linux" && pushd "$MYBUILD/linux" &&
-  sed -is '/select HAVE_STACK_VALIDATION/d' arch/x86/Kconfig && # Fix x86-64
-  sed -is 's/depends on !SMP/& || !MMU/' mm/Kconfig &&          # Fix sh2eb
-
-  # Write miniconfig
-  { echo "# make ARCH=$KARCH allnoconfig KCONFIG_ALLCONFIG=$TARGET.miniconf"
-    echo -e "# make ARCH=$KARCH -j \$(nproc)\n# boot $VMLINUX\n\n"
-    echo "# CONFIG_EMBEDDED is not set"
-
-    # Expand list of =y symbols, first generic then architecture-specific
-    for i in BINFMT_ELF,BINFMT_SCRIPT,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,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 $KEXTRA ; do
-      echo "# architecture ${X:-independent}"
-      sed -E '/^$/d;s/([^,]*)($|,)/CONFIG_\1=y\n/g' <<< "$i"
-      X=specific
-    done
-    [ -n "$BUILTIN" ] && echo -e CONFIG_INITRAMFS_SOURCE="\"$OUTPUT/fs\""
-    echo "$KERNEL_CONFIG"
-  } > "$OUTPUT/miniconfig-$TARGET" &&
-  make ARCH=$KARCH allnoconfig KCONFIG_ALLCONFIG="$OUTPUT/miniconfig-$TARGET" &&
-
-  # 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 &&
-
-  # Build kernel. Copy config, device tree binary, and kernel binary to output
-  make ARCH=$KARCH CROSS_COMPILE="$CROSS_COMPILE" -j $(nproc) &&
-  cp .config "$OUTPUT/linux-fullconfig" || exit 1
-  [ -n "$DTB" ] && { cp "$DTB" "$OUTPUT" || exit 1 ;}
-  cp "$VMLINUX" "$OUTPUT" && cd .. && rm -rf linux && popd || exit 1
-fi
-
-# clean up and package root filesystem for initramfs.
-if [ -z "$BUILTIN" ]; then
-  announce "${CROSS}root.cpio.gz"
-  (cd "$ROOT" && find . | cpio -o -H newc ${CROSS_COMPILE:+--no-preserve-owner}\
-    | gzip) > "$OUTPUT/$CROSS"root.cpio.gz || exit 1
-fi
-
-mv "$LOG/$CROSS".{n,y}
-rmdir "$MYBUILD" "$BUILD" 2>/dev/null || exit 0 # remove if empty, not an error
+#!/usr/bin/printf Moved to mkroot/mkroot.sh\n\c%s
diff --git a/scripts/mkstatus.py b/scripts/mkstatus.py
index ed6dd54..41a1bed 100755
--- a/scripts/mkstatus.py
+++ b/scripts/mkstatus.py
@@ -40,7 +40,7 @@
 # Run a couple sanity checks on input
 
 for i in toystuff:
-  if (i in pending): print "barf %s" % i
+  if (i in pending): print "Pending command not roadmap: %s" % i
 
 unknowns=[]
 for i in toystuff + pending:
diff --git a/scripts/portability.sh b/scripts/portability.sh
index 3af2be5..4241916 100644
--- a/scripts/portability.sh
+++ b/scripts/portability.sh
@@ -2,9 +2,9 @@
 
 source ./configure
 
-if [ -z "$(command -v "${CROSS_COMPILE}${CC}")" ]
+if [ -z "$(command -v "$CROSS_COMPILE$CC")" ]
 then
-  echo "No ${CROSS_COMPILE}${CC} found" >&2
+  echo "No $CROSS_COMPILE$CC found" >&2
   exit 1
 fi
 
@@ -16,26 +16,30 @@
 # Tell linker to do dead code elimination at function level
 if [ "$(uname)" == "Darwin" ]
 then
+  CFLAGS+=" -Wno-deprecated-declarations"
   : ${LDOPTIMIZE:=-Wl,-dead_strip} ${STRIP:=strip}
 else
   : ${LDOPTIMIZE:=-Wl,--gc-sections -Wl,--as-needed} ${STRIP:=strip -s -R .note* -R .comment}
 fi
 
+# Disable a pointless warning only clang produces
+[ -n "$("$CROSS_COMPILE$CC" --version | grep -w clang)" ] &&
+  CFLAGS+=" -Wno-string-plus-int -Wno-invalid-source-encoding"
+
 # Address Sanitizer
-if [ ! -z "$ASAN" ]; then
+if [ -n "$ASAN" ]; then
   # Turn ASan on and disable most optimization to get more readable backtraces.
   # (Technically ASAN is just "-fsanitize=address" and the rest is optional.)
-  ASAN_FLAGS="-fsanitize=address -O1 -g -fno-omit-frame-pointer -fno-optimize-sibling-calls"
-  CFLAGS="$CFLAGS $ASAN_FLAGS"
-  HOSTCC="$HOSTCC $ASAN_FLAGS"
-  NOSTRIP=1
+  export CFLAGS="$CFLAGS -fsanitize=address -O1 -g -fno-omit-frame-pointer -fno-optimize-sibling-calls"
+  export NOSTRIP=1
   # Ignore leaks on exit. TODO
   export ASAN_OPTIONS="detect_leaks=0"
+  # only do this once
   unset ASAN
 fi
 
-# Centos 7 bug workaround, EOL June 30 2024. TODO
-DASHN=-n; wait -n 2>/dev/null; [ $? -eq 2 ] && unset DASHN
+# Probe number of available processors, and add one.
+: ${CPUS:=$(($(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null)+1))}
 
 # If the build is using gnu tools, make them behave less randomly.
 export LANG=c
diff --git a/scripts/runtest.sh b/scripts/runtest.sh
index 5a64767..ce6e0fd 100644
--- a/scripts/runtest.sh
+++ b/scripts/runtest.sh
@@ -2,9 +2,7 @@
 #
 # Copyright 2005 by Rob Landley
 
-# This file defines two main functions, "testcmd" and "optional". The
-# first performs a test, the second enables/disables tests based on
-# configuration options.
+# This file defines three main functions: "testing", "testcmd", and "txpect".
 
 # The following environment variables enable optional behavior in "testing":
 #    DEBUG - Show every command run by test script.
@@ -30,26 +28,13 @@
 # The environment variable "FAILCOUNT" contains a cumulative total of the
 # number of failed tests.
 #
-# The "optional" function is used to skip certain tests (by setting the
-# environment variable SKIP), ala:
-#   optional CFG_THINGY
+# The environment variable "SKIP" says how many upcoming tests to skip,
+# defaulting to 0 and counting down when set to a higher number.
 #
-# The "optional" function checks the environment variable "OPTIONFLAGS",
-# which is either empty (in which case it always clears SKIP) or
-# else contains a colon-separated list of features (in which case the function
-# clears SKIP if the flag was found, or sets it to 1 if the flag was not found).
+# Function "optional" enables/disables tests based on configuration options.
 
-export FAILCOUNT=0
-export SKIP=
-
-# Helper functions
-
-# Check config to see if option is enabled, set SKIP if not.
-
-SHOWPASS=PASS
-SHOWFAIL=FAIL
-SHOWSKIP=SKIP
-
+export FAILCOUNT=0 SKIP=0
+: ${SHOWPASS:=PASS} ${SHOWFAIL:=FAIL} ${SHOWSKIP:=SKIP}
 if tty -s <&1
 then
   SHOWPASS="$(echo -e "\033[1;32m${SHOWPASS}\033[0m")"
@@ -57,48 +42,14 @@
   SHOWSKIP="$(echo -e "\033[1;33m${SHOWSKIP}\033[0m")"
 fi
 
-optional()
-{
-  option=`printf %s "$OPTIONFLAGS" | egrep "(^|:)$1(:|\$)"`
-  # Not set?
-  if [ -z "$1" ] || [ -z "$OPTIONFLAGS" ] || [ ${#option} -ne 0 ]
-  then
-    unset SKIP
-    return
-  fi
-  SKIP=1
-}
+# Helper functions
 
+# Check if VERBOSE= contains a given string. (This allows combining.)
 verbose_has()
 {
   [ "${VERBOSE/$1/}" != "$VERBOSE" ]
 }
 
-skipnot()
-{
-  if verbose_has quiet
-  then
-    eval "$@" 2>/dev/null
-  else
-    eval "$@"
-  fi
-  [ $? -eq 0 ] || SKIPNEXT=1
-}
-
-toyonly()
-{
-  IS_TOYBOX="$("$C" --version 2>/dev/null)"
-  # Ideally we'd just check for "toybox", but toybox sed lies to make autoconf
-  # happy, so we have at least two things to check for.
-  case "$IS_TOYBOX" in
-    toybox*) ;;
-    This\ is\ not\ GNU*) ;;
-    *) SKIPNEXT=1 ;;
-  esac
-
-  "$@"
-}
-
 wrong_args()
 {
   if [ $# -ne 5 ]
@@ -111,65 +62,7 @@
 # Announce success
 do_pass()
 {
-  ! verbose_has nopass && printf "%s\n" "$SHOWPASS: $NAME"
-}
-
-# The testing function
-
-testing()
-{
-  NAME="$CMDNAME $1"
-  wrong_args "$@"
-
-  [ -z "$1" ] && NAME=$2
-
-  [ -n "$DEBUG" ] && set -x
-
-  if [ -n "$SKIP" -o -n "$SKIP_HOST" -a -n "$TEST_HOST" -o -n "$SKIPNEXT" ]
-  then
-    verbose_has quiet && printf "%s\n" "$SHOWSKIP: $NAME"
-    unset SKIPNEXT
-    return 0
-  fi
-
-  echo -ne "$3" > expected
-  [ ! -z "$4" ] && echo -ne "$4" > input || rm -f input
-  echo -ne "$5" | ${EVAL:-eval --} "$2" > actual
-  RETVAL=$?
-
-  # Catch segfaults
-  [ $RETVAL -gt 128 ] && [ $RETVAL -lt 255 ] &&
-    echo "exited with signal (or returned $RETVAL)" >> actual
-  DIFF="$(diff -au${NOSPACE:+w} expected actual)"
-  if [ -n "$DIFF" ]
-  then
-    FAILCOUNT=$(($FAILCOUNT+1))
-    printf "%s\n" "$SHOWFAIL: $NAME"
-  else
-    ! verbose_has nopass && printf "%s\n" "$SHOWPASS: $NAME"
-  fi
-  if ! verbose_has quiet && { [ -n "$DIFF" ] || verbose_has spam; }
-  then
-    [ ! -z "$4" ] && printf "%s\n" "echo -ne \"$4\" > input"
-    printf "%s\n" "echo -ne '$5' |$EVAL $2"
-    [ -n "$DIFF" ] && printf "%s\n" "$DIFF"
-  fi
-
-  [ -n "$DIFF" ] && ! verbose_has all && exit 1
-  rm -f input expected actual
-
-  [ -n "$DEBUG" ] && set +x
-
-  return 0
-}
-
-testcmd()
-{
-  wrong_args "$@"
-
-  X="$1"
-  [ -z "$X" ] && X="$CMDNAME $2"
-  testing "$X" "\"$C\" $2" "$3" "$4" "$5"
+  verbose_has nopass || printf "%s\n" "$SHOWPASS: $NAME"
 }
 
 # Announce failure and handle fallout for txpect
@@ -185,13 +78,102 @@
   ! verbose_has all && exit 1
 }
 
+# Functions test files call directly
+
+# Set SKIP high if option not enabled in $OPTIONFLAGS (unless OPTIONFLAGS blank)
+optional()
+{
+  [ -n "$OPTIONFLAGS" ] && [ "$OPTIONFLAGS" == "${OPTIONFLAGS/:$1:/}" ] &&
+    SKIP=99999 || SKIP=0
+}
+
+# Evalute command line and skip next test when false
+skipnot()
+{
+  if verbose_has quiet
+  then
+    eval "$@" >/dev/null 2>&1
+  else
+    eval "$@"
+  fi
+  [ $? -eq 0 ] || { ((++SKIP)); return 1; }
+}
+
+# Skip this test (rest of command line) when not running toybox.
+toyonly()
+{
+  IS_TOYBOX="$("$C" --version 2>/dev/null)"
+  # Ideally we'd just check for "toybox", but toybox sed lies to make autoconf
+  # happy, so we have at least two things to check for.
+  case "$IS_TOYBOX" in
+    toybox*) ;;
+    This\ is\ not\ GNU*) ;;
+    *) [ $SKIP -eq 0 ] && ((++SKIP)) ;;
+  esac
+
+  "$@"
+}
+
+# Takes five arguments: "name" "command" "result" "infile" "stdin"
+testing()
+{
+  wrong_args "$@"
+
+  [ -z "$1" ] && NAME="$2" || NAME="$1"
+  [ "${NAME#$CMDNAME }" == "$NAME" ] && NAME="$CMDNAME $1"
+
+  [ -n "$DEBUG" ] && set -x
+
+  if [ "$SKIP" -gt 0 ]
+  then
+    verbose_has quiet || printf "%s\n" "$SHOWSKIP: $NAME"
+    ((--SKIP))
+
+    return 0
+  fi
+
+  echo -ne "$3" > ../expected
+  [ ! -z "$4" ] && echo -ne "$4" > input || rm -f input
+  echo -ne "$5" | ${EVAL:-eval --} "$2" > ../actual
+  RETVAL=$?
+
+  # Catch segfaults
+  [ $RETVAL -gt 128 ] &&
+    echo "exited with signal (or returned $RETVAL)" >> actual
+  DIFF="$(cd ..; diff -au${NOSPACE:+w} expected actual)"
+  [ -z "$DIFF" ] && do_pass || VERBOSE=all do_fail
+  if ! verbose_has quiet && { [ -n "$DIFF" ] || verbose_has spam; }
+  then
+    [ ! -z "$4" ] && printf "%s\n" "echo -ne \"$4\" > input"
+    printf "%s\n" "echo -ne '$5' |$EVAL $2"
+    [ -n "$DIFF" ] && printf "%s\n" "$DIFF"
+  fi
+
+  [ -n "$DIFF" ] && ! verbose_has all && exit 1
+  rm -f input ../expected ../actual
+
+  [ -n "$DEBUG" ] && set +x
+
+  return 0
+}
+
+# Wrapper for "testing", adds command name being tested to start of command line
+testcmd()
+{
+  wrong_args "$@"
+
+  testing "${1:-$CMDNAME $2}" "\"$C\" $2" "$3" "$4" "$5"
+}
+
+# Simple implementation of "expect" written in shell.
+
 # txpect NAME COMMAND [I/O/E/Xstring]...
 # Run COMMAND and interact with it: send I strings to input, read O or E
 # strings from stdout or stderr (empty string is "read line of input here"),
 # X means close stdin/stdout/stderr and match return code (blank means nonzero)
 txpect()
 {
-  local NAME CASE VERBOSITY LEN A B X O
+  local NAME CASE VERBOSITY LEN PID A B X O
 
   # Run command with redirection through fifos
   NAME="$CMDNAME $1"
@@ -204,13 +186,14 @@
     return
   fi
   eval "$2" <in-$$ >out-$$ 2>err-$$ &
+  PID=$!
   shift 2
   : {IN}>in-$$ {OUT}<out-$$ {ERR}<err-$$ && rm in-$$ out-$$ err-$$
 
   [ $? -ne 0 ] && { do_fail;return;}
 
   # Loop through challenge/response pairs, with 2 second timeout
-  while [ $# -gt 0 ]
+  while [ $# -gt 0 -a -n "$PID" ]
   do
     VERBOSITY="$VERBOSITY"$'\n'"$1"  LEN=$((${#1}-1))  CASE="$1"  A=  B=
 
@@ -234,29 +217,33 @@
         then
           [ -z "$A" -o "$X" -ne 0 ] && { do_fail;break;}
         else
-          if [ ${1::1} == 'R' ] && [[ "$A" =~ "${1:2}" ]]; then true
+          if [ ${1::1} == 'R' ] && grep -q "${1:2}" <<< "$A"; then true
           elif [ ${1::1} != 'R' ] && [ "$A" == "${1:1}" ]; then true
           else
             # Append the rest of the output if there is any.
             read -t.1 B <&$O
             A="$A$B"
             read -t.1 -rN 9999 B<&$ERR
-            do_fail;break;
+            do_fail
+            break
           fi
         fi
         ;;
 
       # close I/O and wait for exit
       X)
-        exec {IN}<&- {OUT}<&- {ERR}<&-
-        wait
+        exec {IN}<&-
+        wait $PID
         A=$?
+        exec {OUT}<&- {ERR}<&-
         if [ -z "$LEN" ]
         then
           [ $A -eq 0 ] && { do_fail;break;}        # any error
         else
           [ $A != "${1:1}" ] && { do_fail;break;}  # specific value
         fi
+        do_pass
+        return
         ;;
       *) do_fail; break ;;
     esac
@@ -270,65 +257,6 @@
     do_pass
   else
     ! verbose_has quiet && echo "$VERBOSITY" >&2
+    do_fail
   fi
 }
-
-# Recursively grab an executable and all the libraries needed to run it.
-# Source paths beginning with / will be copied into destpath, otherwise
-# the file is assumed to already be there and only its library dependencies
-# are copied.
-
-mkchroot()
-{
-  [ $# -lt 2 ] && return
-
-  echo -n .
-
-  dest=$1
-  shift
-  for i in "$@"
-  do
-    [ "${i:0:1}" == "/" ] || i=$(which $i)
-    [ -f "$dest/$i" ] && continue
-    if [ -e "$i" ]
-    then
-      d=`echo "$i" | grep -o '.*/'` &&
-      mkdir -p "$dest/$d" &&
-      cat "$i" > "$dest/$i" &&
-      chmod +x "$dest/$i"
-    else
-      echo "Not found: $i"
-    fi
-    mkchroot "$dest" $(ldd "$i" | egrep -o '/.* ')
-  done
-}
-
-# Set up a chroot environment and run commands within it.
-# Needed commands listed on command line
-# Script fed to stdin.
-
-dochroot()
-{
-  mkdir tmpdir4chroot
-  mount -t ramfs tmpdir4chroot tmpdir4chroot
-  mkdir -p tmpdir4chroot/{etc,sys,proc,tmp,dev}
-  cp -L testing.sh tmpdir4chroot
-
-  # Copy utilities from command line arguments
-
-  echo -n "Setup chroot"
-  mkchroot tmpdir4chroot $*
-  echo
-
-  mknod tmpdir4chroot/dev/tty c 5 0
-  mknod tmpdir4chroot/dev/null c 1 3
-  mknod tmpdir4chroot/dev/zero c 1 5
-
-  # Copy script from stdin
-
-  cat > tmpdir4chroot/test.sh
-  chmod +x tmpdir4chroot/test.sh
-  chroot tmpdir4chroot /test.sh
-  umount -l tmpdir4chroot
-  rmdir tmpdir4chroot
-}
diff --git a/scripts/single.sh b/scripts/single.sh
index 023ccea..f4f28be 100755
--- a/scripts/single.sh
+++ b/scripts/single.sh
@@ -4,6 +4,8 @@
 
 [ -z "$1" ] && { echo "usage: single.sh command..." >&2; exit 1; }
 
+source scripts/portability.sh
+
 # Add trailing / to PREFIX when it's set but hasn't got one
 [ "$PREFIX" == "${PREFIX%/}" ] && PREFIX="${PREFIX:+$PREFIX/}"
 
@@ -17,7 +19,7 @@
   # Force dependencies to rebuild headers if we build multiplexer after this.
   touch "$KCONFIG_CONFIG"
 fi
-GLOBDEP="$(sed -n 's/CONFIG_\(TOYBOX_[^=]*\)=y/\1/p' "$KCONFIG_CONFIG")"
+GLOBDEP="$($SED -n 's/CONFIG_\(TOYBOX_[^=]*\)=y/\1/p' "$KCONFIG_CONFIG")"
 KCONFIG_CONFIG=.singleconfig
 
 for i in "$@"
@@ -36,15 +38,15 @@
   unset DEPENDS MPDEL
   if [ "$i" == sh ]
   then
-    DEPENDS="$(sed -n 's/USE_\([^(]*\)(NEWTOY([^,]*,.*TOYFLAG_MAYFORK.*/\1/p' toys/*/*.c)"
+    DEPENDS="$($SED -n 's/USE_\([^(]*\)(NEWTOY([^,]*,.*TOYFLAG_MAYFORK.*/\1/p' toys/*/*.c)"
   else
     MPDEL='s/CONFIG_TOYBOX=y/# CONFIG_TOYBOX is not set/;t'
   fi
 
   # Enable stuff this command depends on
-  DEPENDS="$({ echo $DEPENDS $GLOBDEP; sed -n "/^config *$i"'$/,/^$/{s/^[ \t]*depends on //;T;s/[!][A-Z0-9_]*//g;s/ *&& */|/g;p}' $TOYFILE;}| xargs | tr ' ' '|')"
+  DEPENDS="$({ echo $DEPENDS $GLOBDEP; $SED -n "/^config *$i"'$/,/^$/{s/^[ \t]*depends on //;T;s/[!][A-Z0-9_]*//g;s/ *&& */|/g;p}' $TOYFILE;}| xargs | tr ' ' '|')"
   NAME=$(echo $i | tr a-z- A-Z_)
-  sed -ri -e "$MPDEL" \
+  $SED -ri -e "$MPDEL" \
     -e "s/# (CONFIG_($NAME|${NAME}_.*${DEPENDS:+|$DEPENDS})) is not set/\1=y/" \
     "$KCONFIG_CONFIG" || exit 1
 
diff --git a/scripts/test.sh b/scripts/test.sh
index da22f66..c29a9aa 100755
--- a/scripts/test.sh
+++ b/scripts/test.sh
@@ -8,26 +8,28 @@
 
 trap 'kill $(jobs -p) 2>/dev/null; exit 1' INT
 
-rm -rf generated/testdir
-mkdir -p generated/testdir/testdir
+export PREFIX=generated/testdir
+rm -rf "$PREFIX"
+mkdir -p "$PREFIX"/testdir
 
 if [ -z "$TEST_HOST" ]
 then
   if [ $# -ne 0 ]
   then
-    PREFIX=generated/testdir/ scripts/single.sh "$@" || exit 1
+    scripts/single.sh "$@" || exit 1
   else
-    make install_flat PREFIX=generated/testdir || exit 1
+    scripts/install.sh --symlink --force || exit 1
   fi
 fi
 
-cd generated/testdir
+export -n PREFIX
+cd "$PREFIX"
 PATH="$PWD:$PATH"
 TESTDIR="$PWD"
 export LC_COLLATE=C
 
 [ -f "$TOPDIR/generated/config.h" ] &&
-  export OPTIONFLAGS=:$(echo $($SED -nr 's/^#define CFG_(.*) 1/\1/p' "$TOPDIR/generated/config.h") | $SED 's/ /:/g')
+  export OPTIONFLAGS=:$($SED -nr 's/^#define CFG_(.*) 1$/\1/p' "$TOPDIR/generated/config.h" | tr '\n' :)
 
 do_test()
 {
@@ -38,16 +40,16 @@
   if [ -z "$TEST_HOST" ]
   then
     C="$TESTDIR/$CMDNAME"
-    [ ! -e "$C" ] && echo "$CMDNAME disabled" && return
+    [ ! -e "$C" ] && echo "$SHOWSKIP: $CMDNAME disabled" && return
     C="$(dirname $(realpath "$C"))/$CMDNAME"
   else
     C="$(which $CMDNAME 2>/dev/null)"
     [ -z "$C" ] && printf '%s\n' "$SHOWSKIP: no $CMDNAME" && return
   fi
 
-  (. "$1"; cd "$TESTDIR"; touch continue)
+  (. "$1"; cd "$TESTDIR"; echo "$FAILCOUNT" > continue)
   cd "$TESTDIR"
-  [ -e continue ] || exit 1
+  [ -e continue ] && FAILCOUNT=$(($(cat continue)+$FAILCOUNT)) || exit 1
 }
 
 if [ $# -ne 0 ]
diff --git a/tests/bc.test b/tests/bc.test
index 65969b7..710b013 100644
--- a/tests/bc.test
+++ b/tests/bc.test
@@ -5,7 +5,6 @@
 #testcmd "name "args" "result" "infile" "stdin"
 
 BDIR="$FILES/bc"
-TESTDIR="./"
 
 run_bc_test() {
 	tst="$1"
diff --git a/tests/blkid.test b/tests/blkid.test
index 5bfce43..bcd38f3 100755
--- a/tests/blkid.test
+++ b/tests/blkid.test
@@ -28,6 +28,9 @@
 testing "f2fs" "BLKID f2fs" \
   'temp.img: LABEL="myf2fs" UUID="b53d3619-c204-4c0b-8504-36363578491c" TYPE="f2fs"\n' \
   "" ""
+testing "iso" "BLKID iso" \
+  'temp.img: LABEL="CDROM" UUID="2023-02-08-04-47-27-00" TYPE="iso9660"\n' \
+  "" ""
 testing "msdos" "BLKID msdos" \
   'temp.img: SEC_TYPE="msdos" LABEL="mymsdos" UUID="6E1E-0851" TYPE="vfat"\n' \
   "" ""
@@ -53,3 +56,8 @@
 #testing "minix" 'bzcat "$BDIR"/minix.bz2 | blkid -'
 #adfs bfs btrfs cramfs jfs nilfs romfs
 #vfat  // fat32 fat12 fat16
+
+bzcat $FILES/blkid/ext3.bz2 > temp.img
+testcmd "-o value -s" "-o value -s TYPE temp.img" 'ext3\n' "" ""
+testcmd "-o export" "-o export temp.img" 'DEVNAME=temp.img\nLABEL=myext3\nUUID=79d1c877-1a0f-4e7d-b21d-fc32ae3ef101\nSEC_TYPE=ext2\nTYPE=ext3\n' "" ""
+rm temp.img
diff --git a/tests/chattr.test b/tests/chattr.test
index 8f1c4b2..01549b0 100755
--- a/tests/chattr.test
+++ b/tests/chattr.test
@@ -51,7 +51,7 @@
 # f2fs in 5.6+ kernels supports compression, but you can only enable
 # compression on a file while it's still empty, so we skip +c too.
 for attr in "A" "d" "e" "j" "P" "S" "s" "t" "u"; do
-  echo "$_t" > testFile && chattr +$attr testFile 2>/dev/null || SKIPNEXT=1
+  echo "$_t" > testFile && chattr +$attr testFile 2>/dev/null || ((++SKIP))
   # Check that $attr is in the lsattr output, then that - turns it back off.
   testing "toggle $attr" "lsattr testFile | awk '{print \$1}' > attrs;
     grep -q $attr attrs || cat attrs; cat testFile && chattr -$attr testFile &&
@@ -70,7 +70,7 @@
   rm -rf testFile*; $OUT" \
   "$_aA fileA\n$_aA fileB\n$_empty fileA\n$_empty fileB\n" "" ""
 
-touch testFile; chattr -v 1234 testFile 2>/dev/null || SKIPNEXT=1
+touch testFile && chattr -v 1234 testFile 2>/dev/null || ((++SKIP))
 testing "-v version" "lsattr -v testFile | awk '{print \$1}' &&
   chattr -v 4567 testFile && lsattr -v testFile | awk '{print \$1}';
   rm -rf testFile" "1234\n4567\n" "" ""
diff --git a/tests/chmod.test b/tests/chmod.test
index 6c4de0c..97c9e93 100755
--- a/tests/chmod.test
+++ b/tests/chmod.test
@@ -104,13 +104,13 @@
 
 # macOS doesn't allow +s in /tmp
 touch s-supported
-chmod +s s-supported 2>/dev/null || SKIP=1
+chmod +s s-supported 2>/dev/null || SKIP=99
 rm s-supported
 chtest g+s "drwxr-sr-x\n-rw-r-Sr--\n"
 chtest u+s "drwsr-xr-x\n-rwSr--r--\n"
 chtest +s "drwsr-sr-x\n-rwSr-Sr--\n"
 chtest o+s "drwxr-xr-x\n-rw-r--r--\n"
-unset SKIP
+SKIP=0
 
 chtest +t  "drwxr-xr-t\n-rw-r--r-T\n"
 chtest a=r+w+x "drwxrwxrwx\n-rwxrwxrwx\n"
diff --git a/tests/cmp.test b/tests/cmp.test
index ce776e8..9a3da33 100755
--- a/tests/cmp.test
+++ b/tests/cmp.test
@@ -22,7 +22,8 @@
 testcmd "identical files, stdout" "input input2" "" "ab\nc\n" ""
 testcmd "identical files, return code" "input input2 && echo yes" "yes\n" "ab\nc\n" ""
 
-testcmd "EOF, stderr" "input input2 2>&1" "cmp: EOF on input2\n" "ab\nc\nx" ""
+testcmd "EOF, stderr" "input input2 2>&1" \
+  "cmp: EOF on input2 after byte 5, line 2\n" "ab\nc\nx" ""
 testcmd "EOF, return code" "input input2 2>/dev/null || echo yes" "yes\n" "ab\nc\nx" ""
 # The gnu/dammit version fails this because posix says "char" and they don't.
 testcmd "diff, stdout" "input input2 | sed s/byte/char/" \
@@ -32,8 +33,10 @@
 testcmd "-s EOF, return code" "-s input input2 2>&1 || echo yes"  "yes\n" "ab\nc\nx" ""
 testcmd "-s diff, return code" "-s input input2 2>&1 || echo yes" "yes\n" "ab\nx\nx" ""
 
-testcmd "-l EOF, stderr" "-l input input2 2>&1" "cmp: EOF on input2\n" "ab\nc\nx" ""
-testcmd "-l diff and EOF, stdout and stderr" "-l input input2 2>&1 | sort" "4 170 143\ncmp: EOF on input2\n" "ab\nx\nx" ""
+testcmd "-l EOF, stderr" "-l input input2 2>&1" \
+  "cmp: EOF on input2 after byte 5\n" "ab\nc\nx" ""
+testcmd "-l diff and EOF, stdout and stderr" "-l input input2 2>&1 | sort" \
+  "4 170 143\ncmp: EOF on input2 after byte 5\n" "ab\nx\nx" ""
 
 testcmd "-s not exist" "-s input doesnotexist 2>&1 || echo yes" "yes\n" "x" ""
 
diff --git a/tests/comm.test b/tests/comm.test
index 63d9c84..2891c6b 100755
--- a/tests/comm.test
+++ b/tests/comm.test
@@ -4,6 +4,9 @@
 
 #testing "name" "command" "result" "infile" "stdin"
 
-for i in a b c ; do echo $i >> lhs ; done
+echo -e 'a\nb\nc'> lhs
 for i in c d e ; do echo $i >> rhs ; done
-testing "comm" "comm lhs rhs" "a\nb\n\t\tc\n\td\n\te\n" "" ""
+testing "comm" "comm lhs input" "a\nb\n\t\tc\n\td\n\te\n" "c\nd\ne\n" ""
+testing "comm -" "comm - input" "a\nb\n\t\tc\n\td\n\te\n" "c\nd\ne\n" "a\nb\nc\n"
+testing "comm -123 detects missing" "comm - missing 2>/dev/null || echo here" \
+  "here\n" "" ""
diff --git a/tests/cpio.test b/tests/cpio.test
index 183dadd..6f5edde 100755
--- a/tests/cpio.test
+++ b/tests/cpio.test
@@ -6,15 +6,20 @@
 # This means all possible values of strlen(name)+1 % 4,
 # plus file sizes of at least 0-4.
 
+CPIO="cpio${TEST_HOST:+ --quiet}"
+CPI_O="$CPIO -o -H newc"
+
 touch a bb ccc dddd
-testing "name padding" "cpio -o -H newc|cpio -it" "a\nbb\nccc\ndddd\n" "" "a\nbb\nccc\ndddd\n"
+testing "name padding" "$CPI_O|$CPIO -it" "a\nbb\nccc\ndddd\n" \
+  "" "a\nbb\nccc\ndddd\n"
 rm a bb ccc dddd
 
 touch a
 printf '1' >b
 printf '22' >c
 printf '333' >d
-testing "file padding" "cpio -o -H newc|cpio -it" "a\nb\nc\nd\n" "" "a\nb\nc\nd\n"
+testing "file padding" "$CPI_O|$CPIO -it" "a\nb\nc\nd\n" "" \
+  "a\nb\nc\nd\n"
 rm a b c d
 
 touch a
@@ -25,50 +30,55 @@
 # the relevant bit should be here:
 # 110*5 + 4*3 + 2 + 6*3 = 550 + 12 + 20 = 582
 # files are padded to n*4, names are padded to 2 + n*4 due to the header length
-testing "archive length" "cpio -o -H newc|dd ibs=2 skip=291 count=5 2>/dev/null" "TRAILER!!!" "" "a\nbb\nccc\ndddd\n"
-testing "archive magic" "cpio -o -H newc|dd ibs=2 count=3 2>/dev/null" "070701" "" "a\n"
+testing "archive length" "$CPI_O|dd ibs=2 skip=291 count=5 2>/dev/null" "TRAILER!!!" "" "a\nbb\nccc\ndddd\n"
+testing "archive magic" "$CPI_O|dd ibs=2 count=3 2>/dev/null" "070701" "" "a\n"
 # check name length (8 bytes before the empty "crc")
-testing "name length" "cpio -o -H newc|dd ibs=2 skip=47 count=4 2>/dev/null" "00000002" "" "a\n"
-testing "-t" "cpio -o -H newc|cpio -it" "a\nbb\n" "" "a\nbb"
-testing "-t --quiet" "cpio -o -H newc|cpio -it --quiet" "a\nbb\n" "" "a\nbb"
+testing "name length" "$CPI_O|dd ibs=2 skip=47 count=4 2>/dev/null" "00000002" "" "a\n"
+testing "-t" "$CPI_O|$CPIO -it" "a\nbb\n" "" "a\nbb"
+# Only actually tests anything on toybox. :)
+testing "-t --quiet" "$CPI_O|$CPIO -it --quiet" "a\nbb\n" "" "a\nbb"
 mkdir out
-testing "-p" "cpio -p out && find out | sort" "out\nout/a\nout/bb\n" "" "a\nbb"
+testing "-p" "$CPIO -p out && find out | sort" "out\nout/a\nout/bb\n" "" "a\nbb"
 rm -rf out
-testing "-pd" "cpio -pd out && find out | sort" "out\nout/a\nout/bb\n" "" "a\nbb"
+testing "-pd" "$CPIO -pd out && find out | sort" "out\nout/a\nout/bb\n" "" "a\nbb"
 rm a bb ccc dddd
 
 # archive dangling symlinks and empty files even if we cannot open them
 touch a; chmod a-rwx a; ln -s a/cant b
-toyonly testing "archives unreadable empty files" "cpio -o -H newc|cpio -it" "b\na\n" "" "b\na\n"
+toyonly testing "archives unreadable empty files" "$CPI_O|$CPIO -it" "b\na\n" "" "b\na\n"
 chmod u+rw a; rm -f a b
 
 mkdir a
 echo "old" >a/b
-echo "a/b" | cpio -o -H newc >a.cpio
+echo "a/b" | $CPI_O >a.cpio
+testing "directory exists is not an error" \
+  "$CPI_O | { $CPIO -i 2>&1 || echo bad; }" "" "" "a\n"
 rm -rf a
-testing "-i doesn't create leading directories" "cpio -i <a.cpio 2>/dev/null; [ -e a ] || echo yes" "yes\n" "" ""
+testing "-i doesn't create leading directories" \
+  "$CPIO -i <a.cpio 2>/dev/null; [ -e a ] || echo yes" "yes\n" "" ""
 rm -rf a
-testing "-id creates leading directories" "cpio -id <a.cpio && cat a/b" "old\n" "" ""
+testing "-id creates leading directories" "$CPIO -id <a.cpio && cat a/b" \
+  "old\n" "" ""
 rm -rf a a.cpio
 
 mkdir a
 echo "old" >a/b
-find a | cpio -o -H newc >a.cpio
-testing "-i keeps existing files" "echo new >a/b && cpio -i <a.cpio 2>/dev/null; cat a/b" "new\n" "" ""
-testing "-id keeps existing files" "echo new >a/b && cpio -id <a.cpio 2>/dev/null; cat a/b" "new\n" "" ""
-testing "-iu replaces existing files; no error" "echo new >a/b && cpio -iu <a.cpio && cat a/b" "old\n" "" ""
-testing "-idu replaces existing files; no error" "echo new >a/b && cpio -idu <a.cpio && cat a/b" "old\n" "" ""
-testing "skip NUL" "for i in a b; do dd if=/dev/zero bs=512 count=1 2>/dev/null; cat a.cpio; done | cpio -t -H newc" \
+find a | $CPI_O >a.cpio
+testing "-i keeps existing files" "echo new >a/b && $CPIO -i <a.cpio 2>/dev/null; cat a/b" "new\n" "" ""
+testing "-id keeps existing files" "echo new >a/b && $CPIO -id <a.cpio 2>/dev/null; cat a/b" "new\n" "" ""
+testing "-iu replaces existing files; no error" "echo new >a/b && $CPIO -iu <a.cpio && cat a/b" "old\n" "" ""
+testing "-idu replaces existing files; no error" "echo new >a/b && $CPIO -idu <a.cpio && cat a/b" "old\n" "" ""
+testing "skip NUL" "for i in a b; do dd if=/dev/zero bs=512 count=1 2>/dev/null; cat a.cpio; done | $CPIO -t -H newc" \
   "a\na/b\na\na/b\n" "" ""
 rm -rf a a.cpio
 
-testing "error on empty file" "cpio -i 2>/dev/null || echo err" "err\n" "" ""
+testing "error on empty file" "$CPIO -i 2>/dev/null || echo err" "err\n" "" ""
 
 mkdir a
 touch a/file
 ln -s a/symlink a/symlink
 mkdir a/dir
-find a | cpio -o -H newc >a.cpio
+find a | $CPI_O >a.cpio
 if [ "$(id -u)" -eq 0 ]; then
   # We chown between user "root" and the last user in /etc/passwd,
   # and group "root" and the last group in /etc/group.
@@ -80,5 +90,5 @@
   chown -h "${USR}:${GRP}" a/file a/symlink a/dir
 fi
 skipnot [ $(id -u) -eq 0 ]
-testing "-t preserve ownership" "cpio -t <a.cpio >/dev/null && stat -c '%U:%G' a/file a/symlink a/dir" "${USR}:${GRP}\n${USR}:${GRP}\n${USR}:${GRP}\n" "" ""
+testing "-t preserve ownership" "$CPIO -t <a.cpio >/dev/null && stat -c '%U:%G' a/file a/symlink a/dir" "${USR}:${GRP}\n${USR}:${GRP}\n${USR}:${GRP}\n" "" ""
 rm -rf a a.cpio
diff --git a/tests/cut.test b/tests/cut.test
index 889fc18..c354b9b 100755
--- a/tests/cut.test
+++ b/tests/cut.test
@@ -18,7 +18,7 @@
   "one:to:th\nalphabeta\nthe qick \n" "" ""
 testcmd "-b encapsulated" "-b 3-8,4-6 abc.txt" "e:two:\npha:be\ne quic\n" \
   "" ""
-testcmd "-bO overlaps" "--output-delimiter ' ' -b 1-3,2-5,7-9,9-10 abc.txt" \
+testcmd "-bO overlaps" "-O ' ' -b 1-3,2-5,7-9,9-10 abc.txt" \
   "one:t o:th\nalpha beta\nthe q ick \n" "" ""
 testcmd "high-low error" "-b 8-3 abc.txt 2>/dev/null || echo err" "err\n" \
   "" ""
@@ -36,7 +36,7 @@
 toyonly testcmd "-C test1.txt" '-C -1 "$FILES/utf8/test1.txt"' "l̴̗̞̠\n" "" ""
 
 # substitute for awk
-toyonly testcmd "-DF" "-DF 2,7,5" \
+testcmd "-DF" "-DF 2,7,5" \
   "said and your\nare\nis demand. supply\nforecast :\nyou you better,\n\nEm: Took hate\n" "" \
 "Bother, said Pooh. It's your husband, and he has a gun.
 Cheerios are donut seeds.
@@ -45,7 +45,7 @@
 Apple: you can buy better, but you can't pay more.
 Subcalifragilisticexpialidocious.
 Auntie Em: Hate you, hate Kansas. Took the dog. Dorothy."
-toyonly testcmd "-DF 2" "-DF 7,1,3-6,2-5" \
+testcmd "-DF 2" "-DF 7,1,3-6,2-5" \
   "seven one three four five six two three four five\n" "" \
   "one two three four five six seven eight nine\n"
 
diff --git a/tests/date.test b/tests/date.test
index dfcefb2..9777edb 100644
--- a/tests/date.test
+++ b/tests/date.test
@@ -97,3 +97,6 @@
 # Can we parse date's own output format?
 testing "round trip" 'TZ=$tz date -d "$(TZ=$tz date -d @1598476818)"' \
   "Wed Aug 26 23:20:18 CEST 2020\n" "" ""
+
+toyonly testcmd "-D with -d" "-uD '%s' -d '1234567890'" \
+  "Fri Feb 13 23:31:30 UTC 2009\n" "" ""
diff --git a/tests/diff.test b/tests/diff.test
index f78eaa6..ddca476 100644
--- a/tests/diff.test
+++ b/tests/diff.test
@@ -5,36 +5,106 @@
 seq 10 > left
 seq 11 > right
 
-testing "unknown argument" 'diff --oops left right 2>/dev/null ; echo $?' "2\n" "" ""
-testing "missing" 'diff missing1 missing2 2>/dev/null ; echo $?' "2\n" "" ""
+testcmd "unknown argument" '--oops left right 2>/dev/null ; echo $?' "2\n" "" ""
+testcmd "missing" 'missing1 missing2 2>/dev/null ; echo $?' "2\n" "" ""
 
-testing "- -" 'diff - - ; echo $?' "0\n" "" "whatever"
+testcmd "- -" '- - ; echo $?' "0\n" "" "whatever"
 
-expected='--- lll
+testcmd "simple" "-u -L lll -L rrr left right" '--- lll
 +++ rrr
 @@ -8,3 +8,4 @@
  8
  9
  10
 +11
-'
-# Hm this only gives unified diffs?
-testing "simple" "diff -L lll -L rrr left right" "$expected" "" ""
+' "" ""
 
-
-expected='--- tree1/file
-+++ tree2/file
-@@ -1 +1 @@
--foo
-+food
-'
 mkdir -p tree1 tree2
 echo foo > tree1/file
 echo food > tree2/file
 
-testing "-r" "diff -r -L tree1/file -L tree2/file tree1 tree2 |tee out" "$expected" "" ""
+# Debian's diff gratuitously echoes its command line with -r. No idea why.
+testcmd "-r" "-u -r -L tree1/file -L tree2/file tree1 tree2 | grep -v ^diff" \
+  '--- tree1/file
++++ tree2/file
+@@ -1 +1 @@
+-foo
++food
+' "" ""
 
 echo -e "hello\r\nworld\r\n"> a
 echo -e "hello\nworld\n"> b
-testing "--strip-trailing-cr off" "diff -q a b" "Files a and b differ\n" "" ""
-testing "--strip-trailing-cr on" "diff -u --strip-trailing-cr a b" "" "" ""
+testcmd "--strip-trailing-cr off" "-q a b" "Files a and b differ\n" "" ""
+testcmd "--strip-trailing-cr on" '-u --strip-trailing-cr a b; echo $?' \
+  "0\n" "" ""
+
+echo -e "1\n2" > aa
+echo -e "1\n3" > bb
+testcmd "line format" "--unchanged-line-format=U%l --old-line-format=D%l --new-line-format=A%l aa bb" "U1D2A3" "" ""
+testcmd "line format empty" "--unchanged-line-format= --old-line-format=D%l --new-line-format=A%l aa bb" "D2A3" "" ""
+
+mkfifo fifo1
+mkfifo fifo2
+echo -e "1\n2" > fifo1&
+echo -e "1\n3" > fifo2&
+testcmd "fifos" "-u -L fifo1 -L fifo2 fifo1 fifo2" '--- fifo1
++++ fifo2
+@@ -1,2 +1,2 @@
+ 1
+-2
++3
+' "" ""
+
+echo -e 'int bar() {
+}
+
+int foo() {
+}
+
+int baz() {
+  1
+  {2
+  3
+  4
+  foo
+}
+'> a
+echo -e 'int barbar() {
+}
+
+int foo() {
+}
+
+int baz() {
+  1a
+  {2
+  3
+  4
+  bar
+}
+'> b
+testcmd 'show function' "--show-function-line=' {$' -U1 -L lll -L rrr a b" \
+'--- lll
++++ rrr
+@@ -1,2 +1,2 @@
+-int bar() {
++int barbar() {
+ }
+@@ -7,3 +7,3 @@ int foo() {
+ int baz() {
+-  1
++  1a
+   {2
+@@ -11,3 +11,3 @@ int baz() {
+   4
+-  foo
++  bar
+ }
+' \
+'' ''
+
+seq 1 100000 > one
+seq 1 4 100000 > two
+testcmd 'big hunk' '-u --label nope --label nope one two' \
+  "$(echo -e '--- nope\n+++ nope\n@@ -1,100000 +1,25000 @@'; for((i=1;i<=100000;i++)); do (((i-1)&3)) && echo "-$i" || echo " $i"; done)\n" '' ''
+rm one two
diff --git a/tests/factor.test b/tests/factor.test
index b556c3a..9015185 100755
--- a/tests/factor.test
+++ b/tests/factor.test
@@ -20,3 +20,8 @@
 testing "3 6 from stdin" "factor" "3: 3\n6: 2 3\n" "" "3 6"
 testing "stdin newline" "factor" "3: 3\n6: 2 3\n" "" "3\n6\n"
 
+testing "-h" "factor -h $(((1<<63)-26))" \
+  "9223372036854775782: 2 3^4 17 23 319279 456065899\n" "" ""
+testing "-x" "factor -x $(((1<<63)-20))" \
+  "7fffffffffffffec: 2 2 3 283 43f2ba978e663\n" "" ""
+
diff --git a/tests/files/blkid/iso.bz2 b/tests/files/blkid/iso.bz2
new file mode 100644
index 0000000..f6babd5
--- /dev/null
+++ b/tests/files/blkid/iso.bz2
Binary files differ
diff --git a/tests/grep.test b/tests/grep.test
index dbab4cc..c7fab92 100755
--- a/tests/grep.test
+++ b/tests/grep.test
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+# TODO: several tests need to check both fast and slow paths
+
 [ -f testing.sh ] && . testing.sh
 
 # Copyright 2013 by Kyungsu Kim <kaspyx@gmail.com>
@@ -7,174 +9,165 @@
 
 #testing "name" "command" "result" "infile" "stdin"
 
-testing "-c" "grep -c 123 input" "3\n" "123\ncount 123\n123\nfasdfasdf" ""
+testcmd "-c" "-c 123 input" "3\n" "123\ncount 123\n123\nfasdfasdf" ""
 
 echo -e "this is test" > foo
 echo -e "this is test2" > foo2
 echo -e "this is foo3" > foo3
-testing "-l" "grep -l test foo foo2 foo3" "foo\nfoo2\n" "" ""
-testing "-L" "grep -L test foo foo2 foo3" "foo3\n" "" ""
+testcmd "-l" "-l test foo foo2 foo3" "foo\nfoo2\n" "" ""
+testcmd "-L" "-L test foo foo2 foo3" "foo3\n" "" ""
 rm foo foo2 foo3
 
-testing "-q" "grep -q test input && echo yes" "yes\n" "this is a test\n" ""
-testing "-E" "grep -E '[0-9]' input" "1234123asdfas123123\n1\n" \
+testcmd "-q" "-q test input && echo yes" "yes\n" "this is a test\n" ""
+testcmd "-E" "-E '[0-9]' input" "1234123asdfas123123\n1\n" \
   "1234123asdfas123123\nabc\n1\nabcde" ""
-testing "-e" "grep -e '[0-9]' input" "1234123asdfas123123\n1\n" \
+testcmd "-e" "-e '[0-9]' input" "1234123asdfas123123\n1\n" \
   "1234123asdfas123123\nabc\n1\nabcde" ""
-testing "-e -e" "grep -e one -e two -e three input" \
+testcmd "-e -e" "-e one -e two -e three input" \
   "two\ntwo\nthree\none\n" "two\ntwo\nthree\nand\none\n" ""
-testing "-F" "grep -F is input" "this is test\nthis is test2\n" \
+testcmd "-F" "-F is input" "this is test\nthis is test2\n" \
   "this is test\nthis is test2\ntest case" ""
+testcmd "-Fo ''" "-Fo ''" "" "" "hello\n"
+testcmd "-Fw ''" "-Fw ''" "" "" "hello\n"
+testcmd "-Fw '' 2" "-Fw ''" "\n" "" "\n"
+testcmd "-F is really fixed" "-F '.[x]'" "c.[x]d\n" "" "axb\nc.[x]d\n"
 
 echo -e "this is test\nthis is test2\ntest case" > foo
 echo -e "hello this is test" > foo2
 echo -e "hi hello" > foo3
-testing "-H" "grep -H is foo foo2 foo3" "foo:this is test\nfoo:this is test2\nfoo2:hello this is test\n" "" ""
+testcmd "-H" "-H is foo foo2 foo3" \
+  "foo:this is test\nfoo:this is test2\nfoo2:hello this is test\n" "" ""
 rm foo foo2 foo3
 
-testing "-b" "grep -b is input" "0:this is test\n13:this is test2\n" \
+testcmd "-b" "-b is input" "0:this is test\n13:this is test2\n" \
   "this is test\nthis is test2\ntest case" ""
-testing "-i" "grep -i is input" "thisIs test\nthis is test2\n" \
+testcmd "-i" "-i is input" "thisIs test\nthis is test2\n" \
   "thisIs test\nthis is test2\ntest case" ""
-testing "-n" "grep -n is input" "1:this is test\n2:this is test2\n" \
+testcmd "-n" "-n is input" "1:this is test\n2:this is test2\n" \
   "this is test\nthis is test2\ntest case" ""
-testing "-o" "grep -o is input" "is\nis\nis\nis\n" \
+testcmd "-o" "-o is input" "is\nis\nis\nis\n" \
   "this is test\nthis is test2\ntest case" ""
-testing "-s" "grep -hs hello asdf input 2>&1" "hello\n" "hello\n" ""
-testing "-v" "grep -v abc input" "1234123asdfas123123\n1ABa\n" \
+testcmd "-s" "-hs hello asdf input 2>&1" "hello\n" "hello\n" ""
+testcmd "-v" "-v abc input" "1234123asdfas123123\n1ABa\n" \
   "1234123asdfas123123\n1ABabc\nabc\n1ABa\nabcde" ""
-testing "-w" "grep -w abc input" "abc\n123 abc\nabc 123\n123 abc 456\n" \
+testcmd "-w" "-w abc input" "abc\n123 abc\nabc 123\n123 abc 456\n" \
   "1234123asdfas123123\n1ABabc\nabc\n1ABa\nabcde\n123 abc\nabc 123\n123 abc 456\n" ""
-testing "-x" "grep -x abc input" "abc\n" \
-  "aabcc\nabc\n" ""
+testcmd "-x" "-x abc input" "abc\n" "aabcc\nabc\n" ""
 
-testing "-H (standard input)" "grep -H abc" "(standard input):abc\n" \
-  "" "abc\n"
-testing "-l (standard input)" "grep -l abc" "(standard input)\n" \
-  "" "abc\n"
-testing "-n two inputs" "grep -hn def - input" "2:def\n2:def\n" \
+testcmd "-H (standard input)" "-H abc" "(standard input):abc\n" "" "abc\n"
+testcmd "-l (standard input)" "-l abc" "(standard input)\n" "" "abc\n"
+testcmd "-n two inputs" "-hn def - input" "2:def\n2:def\n" \
   "abc\ndef\n" "abc\ndef\n"
 
-testing "pattern with newline" "grep 'abc
-def' input" "aabcc\nddeff\n" \
+testcmd "pattern with newline" $'"abc\ndef" input' "aabcc\nddeff\n" \
   "aaaa\naabcc\n\dddd\nddeff\nffff\n" ""
 
-testing "-lH" "grep -lH abc input" "input\n" "abc\n" ""
-testing "-cn" "grep -cn abc input" "1\n" "abc\n" ""
-testing "-cH" "grep -cH abc input" "input:1\n" "abc\n" ""
-testing "-qs" "grep -qs abc none input && echo yes" "yes\n" "abc\n" ""
-testing "-hl" "grep -hl abc input" "input\n" "abc\n" ""
-testing "-b stdin" "grep -b one" "0:one\n4:one\n8:one\n" "" "one\none\none\n"
-testing "-o overlap" "grep -bo aaa" "1:aaa\n" "" "baaaa\n"
+testcmd "-lH" "-lH abc input" "input\n" "abc\n" ""
+testcmd "-cn" "-cn abc input" "1\n" "abc\n" ""
+testcmd "-cH" "-cH abc input" "input:1\n" "abc\n" ""
+testcmd "-qs" "-qs abc none input && echo yes" "yes\n" "abc\n" ""
+testcmd "-hl" "-hl abc input" "input\n" "abc\n" ""
+testcmd "-b stdin" "-b one" "0:one\n4:one\n8:one\n" "" "one\none\none\n"
+testcmd "-o overlap" "-bo aaa" "1:aaa\n" "" "baaaa\n"
 # nonobvious: -co counts lines, not matches
-testing "-co" "grep -co one input" "1\n" "one one one\n" ""
-testing "-nom" "grep -nom 2 one" "1:one\n1:one\n1:one\n2:one\n2:one\n" \
+testcmd "-co" "-co one input" "1\n" "one one one\n" ""
+testcmd "-nom" "-nom 2 one" "1:one\n1:one\n1:one\n2:one\n2:one\n" \
   "" "one one one\none one\none"
-toyonly testing "-vo" "grep -vo one input" "two\nthree\n" "onetwoonethreeone\n" ""
-testing "no newline" "grep -h one input -" \
+toyonly testcmd "-vo" "-vo one input" "two\nthree\n" "onetwoonethreeone\n" ""
+testcmd "no newline" "-h one input -" \
   "hello one\nthere one\n" "hello one" "there one"
 
-testing "-e multi" "grep -e one -ethree input" \
-  "three\none\n" "three\ntwo\none\n" ""
+testcmd "-e multi" "-e one -ethree input" "three\none\n" "three\ntwo\none\n" ""
 # Suppress filenames for recursive test because dunno order they'd occur in
 mkdir sub
 echo -e "one\ntwo\nthree" > sub/one
 echo -e "three\ntwo\none" > sub/two
-testing "-hr" "grep -hr one sub" "one\none\n" "" ""
-testing "-r file" "grep -r three sub/two" "three\n" "" ""
-testing "-r dir" "grep -r one sub | sort" "sub/one:one\nsub/two:one\n" \
+testcmd "-hr" "-hr one sub" "one\none\n" "" ""
+testcmd "-r file" "-r three sub/two" "three\n" "" ""
+testcmd "-r dir" "-r one sub | sort" "sub/one:one\nsub/two:one\n" \
   "" ""
 rm -rf sub
 
 # -x exact match overrides -F's "empty string matches whole line" behavior
-testing "-Fx ''" "grep -Fx '' input" "" "one one one\n" ""
-testing "-F ''" "grep -F '' input" "one one one\n" "one one one\n" ""
-testing "-F -e blah -e ''" "grep -F -e blah -e '' input" "one one one\n" \
+testcmd "-Fx ''" "-Fx '' input" "" "one one one\n" ""
+testcmd "-F ''" "-F '' input" "one one one\n" "one one one\n" ""
+testcmd "-F -e blah -e ''" "-F -e blah -e '' input" "one one one\n" \
   "one one one\n" ""
-testing "-Fxv -e subset" "grep -Fxv -e bbswitch-dkms -e dkms" "" "" \
-  "bbswitch-dkms\n"
-testing "-e blah -e ''" "grep -e blah -e '' input" "one one one\n" \
-  "one one one\n" ""
-testing "-w ''" "grep -w '' input" "" "one one one\n" ""
-testing "-w '' 2" "grep -w '' input" "one  two\n" "one  two\n" ""
-testing "-w \\1" "grep -wo '\\(x\\)\\1'" "xx\n" "" "xx"
-testing "-o ''" "grep -o '' input" "" "one one one\n" ""
-testing "backref" 'grep -e "a\(b\)" -e "b\(c\)\1"' "bcc\nab\n" \
-  "" "bcc\nbcb\nab\n"
+testcmd "-Fxv -e subset" "-Fxv -e bbswitch-dkms -e dkms" "" "" "bbswitch-dkms\n"
+testcmd "-e blah -e ''" "-e blah -e '' input" "one one one\n" "one one one\n" ""
+testcmd "-w ''" "-w '' input" "" "one one one\n" ""
+testcmd "-w '' 2" "-w '' input" "one  two\n" "one  two\n" ""
+testcmd "-w \\1" "-wo '\\(x\\)\\1'" "xx\n" "" "xx"
+testcmd "-o ''" "-o '' input" "" "one one one\n" ""
+testcmd "backref" '-e "a\(b\)" -e "b\(c\)\1"' "bcc\nab\n" "" "bcc\nbcb\nab\n"
 
-testing "-A" "grep -A 2 yes" "yes\nno\nno\n--\nyes\nno\nno\nyes\nno\n" \
+testcmd "-A" "-A 2 yes" "yes\nno\nno\n--\nyes\nno\nno\nyes\nno\n" \
   "" "yes\nno\nno\nno\nyes\nno\nno\nyes\nno"
-testing "-B" "grep -B 1 yes" "no\nyes\n--\nno\nyes\nno\nyes\n" \
+testcmd "-B" "-B 1 yes" "no\nyes\n--\nno\nyes\nno\nyes\n" \
   "" "no\nno\nno\nyes\nno\nno\nyes\nno\nyes"
-testing "-C" "grep -C 1 yes" \
-  "yes\nno\n--\nno\nyes\nno\nno\nyes\nno\nyes\nno\n" \
+testcmd "-C" "-C 1 yes" "yes\nno\n--\nno\nyes\nno\nno\nyes\nno\nyes\nno\n" \
   "" "yes\nno\nno\nno\nyes\nno\nno\nyes\nno\nyes\nno\nno"
-testing "-HnC" "grep -HnC1 two" \
+testcmd "-HnC" "-HnC1 two" \
   "(standard input)-1-one\n(standard input):2:two\n(standard input)-3-three\n" \
   "" "one\ntwo\nthree"
 
 # Context lines weren't showing -b
-testing "-HnbB1" "grep -HnbB1 f input" \
+testcmd "-HnbB1" "-HnbB1 f input" \
   "input-3-8-three\ninput:4:14:four\ninput:5:19:five\n" \
   "one\ntwo\nthree\nfour\nfive\n" ""
 
-testing "-q match overrides error" \
-  "grep -q hello missing input 2>/dev/null && echo yes" "yes\n" "hello\n" ""
-testing "-q not found is 1" \
-  'grep -q hello input || echo $?' "1\n" "x" ""
-testing "-q missing is 2" \
-  'grep -q hello missing missing 2>/dev/null || echo $?' "2\n" "" ""
-testing "-q missing survives exists but not found" \
-  'grep -q hello missing missing input 2>/dev/null || echo $?' "2\n" "" ""
-testing "not found retained past match" \
-  'grep hello missing input 2>/dev/null || echo $?' \
-  "input:hello\n2\n" "hello\n" ""
+testcmd "-q match overrides error" \
+  "-q hello missing input 2>/dev/null && echo yes" "yes\n" "hello\n" ""
+testcmd "-q not found is 1" '-q hello input || echo $?' "1\n" "x" ""
+testcmd "-q missing is 2" \
+  '-q hello missing missing 2>/dev/null || echo $?' "2\n" "" ""
+testcmd "-q missing survives exists but not found" \
+  '-q hello missing missing input 2>/dev/null || echo $?' "2\n" "" ""
+testcmd "not found retained past match" \
+  'hello missing input 2>/dev/null || echo $?' "input:hello\n2\n" "hello\n" ""
 touch empty
-testing "one match good enough for 0" \
-  'grep hello input empty && echo $?' 'input:hello\n0\n' 'hello\n' ''
+testcmd "one match good enough for 0" \
+  'hello input empty && echo $?' 'input:hello\n0\n' 'hello\n' ''
 rm empty
 
-testing "-o ''" "grep -o ''" "" "" "one two three\none two\none\n"
-testing '' "grep -o -e '' -e two" "two\ntwo\n" "" \
-  "one two three\none two\none\n"
+testcmd "-o ''" "-o ''" "" "" "one two three\none two\none\n"
+testcmd '' "-o -e '' -e two" "two\ntwo\n" "" "one two three\none two\none\n"
 
 echo "one\ntwo\nthree" > test
-testing "-l overrides -C" "grep -l -C1 two test input" "test\ninput\n" \
+testcmd "-l overrides -C" "-l -C1 two test input" "test\ninput\n" \
   "three\ntwo\none\n" ""
 rm test
 
 # match after NUL byte
-testing "match after NUL byte" "grep -a two" "one\0and two three\n" \
+testcmd "match after NUL byte" "-a two" "one\0and two three\n" \
   "" 'one\0and two three'
 
 # BREs versus EREs
-testing "implicit BRE |" "grep 'uno|dos'" "uno|dos\n" \
-  "" "uno\ndos\nuno|dos\n"
-testing "explicit BRE |" "grep -e 'uno|dos'" "uno|dos\n" \
-  "" "uno\ndos\nuno|dos\n"
-testing "explicit ERE |" "grep -E 'uno|dos'" "uno\ndos\nuno|dos\n" \
+testcmd "implicit BRE |" "'uno|dos'" "uno|dos\n" "" "uno\ndos\nuno|dos\n"
+testcmd "explicit BRE |" "-e 'uno|dos'" "uno|dos\n" "" "uno\ndos\nuno|dos\n"
+testcmd "explicit ERE |" "-E 'uno|dos'" "uno\ndos\nuno|dos\n" \
   "" "uno\ndos\nuno|dos\n"
 
-testing "" "grep -o -e iss -e ipp" "iss\niss\nipp\n" "" "mississippi"
-testing "" "grep -o -e gum -e rgu" "rgu\n" "" "argument"
+testcmd "" "-o -e iss -e ipp" "iss\niss\nipp\n" "" "mississippi"
+testcmd "" "-o -e gum -e rgu" "rgu\n" "" "argument"
 
-testing "early failure" 'grep --what 2>/dev/null || echo $?' "2\n" "" ""
+testcmd "early failure" '--what 2>/dev/null || echo $?' "2\n" "" ""
 
-testing "" 'grep abc ; echo $?' "abcdef\n0\n" "" "abcdef\n"
-testing "" 'grep abc doesnotexist input 2>/dev/null; echo $?' \
+testcmd "" 'abc ; echo $?' "abcdef\n0\n" "" "abcdef\n"
+testcmd "" 'abc doesnotexist input 2>/dev/null; echo $?' \
   "input:abcdef\n2\n" "abcdef\n" ""
 mkdir sub
 ln -s nope sub/link
-testing "" 'grep -r walrus sub 2>/dev/null; echo $?' "1\n" "" ""
+testcmd "" '-r walrus sub 2>/dev/null; echo $?' "1\n" "" ""
 rm -rf sub
 
 # --exclude-dir
-mkdir sub
-mkdir sub/yes
+mkdir -p sub/yes
 echo "hello world" > sub/yes/test
 mkdir sub/no
 echo "hello world" > sub/no/test
-testing "--exclude-dir" 'grep --exclude-dir=no -r world sub' "sub/yes/test:hello world\n" "" ""
+testcmd "--exclude-dir" '--exclude-dir=no -r world sub' \
+  "sub/yes/test:hello world\n" "" ""
 rm -rf sub
 
 # -r and -R differ in that -R will dereference symlinks to directories.
@@ -182,28 +175,52 @@
 echo "hello" > dir/f
 mkdir sub
 ln -s ../dir sub/link
-testing "" "grep -rh hello sub 2>/dev/null || echo err" "err\n" "" ""
-testing "" "grep -Rh hello sub" "hello\n" "" ""
+testcmd "" "-rh hello sub 2>/dev/null || echo err" "err\n" "" ""
+testcmd "" "-Rh hello sub" "hello\n" "" ""
 rm -rf sub real
 
 # -F multiple matches
-testing "-F multiple" "grep -F h input" "this is hello\nthis is world\n" \
+testcmd "-F multiple" "-F h input" "this is hello\nthis is world\n" \
   "missing\nthis is hello\nthis is world\nmissing" ""
-testing "-Fi multiple" "grep -Fi h input" "this is HELLO\nthis is WORLD\n" \
+testcmd "-Fi multiple" "-Fi h input" "this is HELLO\nthis is WORLD\n" \
   "missing\nthis is HELLO\nthis is WORLD\nmissing" ""
-testing "-F empty multiple" "grep -Fi '' input" \
+testcmd "-F empty multiple" "-Fi '' input" \
   "missing\nthis is HELLO\nthis is WORLD\nmissing\n" \
   "missing\nthis is HELLO\nthis is WORLD\nmissing" ""
-testing "-Fx" "grep -Fx h input" "h\n" \
+testcmd "-Fx" "-Fx h input" "h\n" \
   "missing\nH\nthis is hello\nthis is world\nh\nmissing" ""
-testing "-Fix" "grep -Fix h input" "H\nh\n" \
+testcmd "-Fix" "-Fix h input" "H\nh\n" \
   "missing\nH\nthis is HELLO\nthis is WORLD\nh\nmissing" ""
-testing "-f /dev/null" "grep -f /dev/null" "" "" "hello\n"
-testing "-z with \n in pattern" "grep -f input" "hi\nthere\n" "i\nt" "hi\nthere"
+testcmd "-F bucket sort" "-F '\.zip'" '\\.zip\n' '' '\\.zip\n'
+testcmd "-f /dev/null" "-f /dev/null" "" "" "hello\n"
 
-testing "print zero length match" "grep '[0-9]*'" "abc\n" "" "abc\n"
-testing "-o skip zero length match" "grep -o '[0-9]*'" "1234\n" "" "a1234b"
+# -z doesn't apply to the \n in -e or -f patterns
+# Because x\n becomes "x" and "" the second of which matches every line.
+testcmd '-z patter\n' "-ze $'x\n' | xxd -pc0" \
+  '6f6e650a74776f0a74687265650a00\n' '' 'one\ntwo\nthree\n'
+testcmd "-z patter\n 2" "-zof input | xxd -pc0" "69007400\n" "i\nt" "hi\nthere"
+testcmd '-lZ' '-lZ ^t input' 'input\0' 'one\ntwo' ''
+
+# other implementations get this wrong without -a, but right with -a???
+toyonly testcmd '-l ^ after \0' '-l ^t' '' 'one\0two' ''
+
+testcmd "print zero length match" "'[0-9]*'" "abc\n" "" "abc\n"
+testcmd "-o skip zero length match" "-o '[0-9]*'" "1234\n" "" "a1234b"
 # Bit of a hack, but other greps insert gratuitous \e[K clear-to-EOL
-testing "--color highlights all matches" \
-  "grep --color=always def | grep -o '[[][0-9;]*[Km]def.[[]m' | wc -l" \
+testcmd "--color highlights all matches" \
+  "--color=always def | grep -o '[[][0-9;]*[Km]def.[[]m' | wc -l" \
   "2\n" "" "abcdefghidefjkl\n"
+seq 1 100002 | base64 > testfile
+testing "speed" "timeout 5 grep -f testfile testfile 2>/dev/null | wc -l" \
+  "10332\n" "" ""
+rm -f testfile
+
+# Fast path tests
+
+testcmd 'initial \' '\\.jar' 'bell.jar\n' '' 'bell.jar\n'
+testcmd '^$' '^\$' '\n' '' 'one\n\ntwo\n'
+testcmd 'middle ^ not special' 'a^' 'a^b\n' '' 'a^b\nb^a\n'
+# Quoted to protect it from the shell, grep should just see '$b'
+testcmd 'middle $ not special' "'\$b'" 'a$b\n' '' 'a$b\nb$a\n'
+
+testcmd 'grep -of' '-of input' 'abc\n' 'a.c\n' 'abcdef\n'
diff --git a/tests/gunzip.test b/tests/gunzip.test
old mode 100644
new mode 100755
diff --git a/tests/head.test b/tests/head.test
index 4e4c01b..e23b70d 100755
--- a/tests/head.test
+++ b/tests/head.test
@@ -4,30 +4,33 @@
 
 #testing "name" "command" "result" "infile" "stdin"
 
-testing "head, stdin" "head -n 1 && echo yes" "one\nyes\n" "" "one\ntwo"
-testing "head, stdin via -" "head -n 1 - && echo yes" "one\nyes\n" "" "one\ntwo"
-testing "head, file" "head input -n 1 && echo yes" "one\nyes\n" "one\ntwo" ""
-testing "-number" "head -2 input && echo yes" "one\ntwo\nyes\n" \
+testcmd "stdin" "-n 1 && echo yes" "one\nyes\n" "" "one\ntwo"
+testcmd "stdin via -" "-n 1 - && echo yes" "one\nyes\n" "" "one\ntwo"
+testcmd "file" "input -n 1 && echo yes" "one\nyes\n" "one\ntwo" ""
+testcmd "-number" "-2 input && echo yes" "one\ntwo\nyes\n" \
 	"one\ntwo\nthree\nfour" ""
-testing "head, default lines" "head" "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" "" "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12"
+testcmd "default lines" "" "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" "" "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12"
 
 # coreutils & busybox name stdin as "standard input", toybox uses "-"
-testing "-v file" "head -v -n 1 input" "==> input <==\none\n" "one\ntwo\n" ""
-testing "-v stdin" "head -v -n 1 | sed 's/==> standard input <==/==> - <==/'" \
+testcmd "-v file" "-v -n 1 input" "==> input <==\none\n" "one\ntwo\n" ""
+testcmd "-v stdin" "-v -n 1 | sed 's/standard input/-/'" \
 	"==> - <==\none\n" "" "one\ntwo\n"
 
-testing "file and stdin" "head -n 1 input - | sed 's/==> standard input <==/==> - <==/'" \
+testcmd "file and stdin" "-n 1 input - | sed 's/standard input/-/'" \
 	"==> input <==\none\n\n==> - <==\nfoo\n" "one\ntwo\n" "foo\nbar\n"
 
 echo "foo
 bar
 baz" > file1
-testing "head, multiple files" "head -n 2 input file1" "==> input <==\none\ntwo\n\n==> file1 <==\nfoo\nbar\n" "one\ntwo\nthree\n" ""
-testing "-q, multiple files" "head -q -n 2 input file1" "one\ntwo\nfoo\nbar\n" \
+testcmd "multiple files" "-n 2 input file1" \
+  "==> input <==\none\ntwo\n\n==> file1 <==\nfoo\nbar\n" "one\ntwo\nthree\n" ""
+testcmd "-q, multiple files" "-q -n 2 input file1" "one\ntwo\nfoo\nbar\n" \
 	"one\ntwo\nthree\n" ""
 rm file1
 
-testing "-c 3" "head -c 3" "one" "" "one\ntwo"
-testing "-c bigger than input" "head -c 3" "a" "" "a"
-testing "-c 3 -n 1" "head -c 3 -n 1" "one\n" "" "one\ntwo"
-testing "-n 1 -c 3" "head -n 1 -c 3" "one" "" "one\ntwo"
+testcmd "-c 3" "-c 3" "one" "" "one\ntwo"
+testcmd "-c bigger than input" "-c 3" "a" "" "a"
+testcmd "-c 3 -n 1" "-c 3 -n 1" "one\n" "" "one\ntwo"
+testcmd "-n 1 -c 3" "-n 1 -c 3" "one" "" "one\ntwo"
+testing "unget" 'while read i; do echo =$i; head -n 1; done < input' \
+  '=one\ntwo\n=three\nfour\n=five\n' 'one\ntwo\nthree\nfour\nfive\n' ''
diff --git a/tests/httpd.test b/tests/httpd.test
new file mode 100755
index 0000000..ac07c39
--- /dev/null
+++ b/tests/httpd.test
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+[ -f testing.sh ] && . testing.sh
+
+#testing "name" "command" "result" "infile" "stdin"
+
+testcmd "static file" \
+  "\"\$FILES\" | sed 's/\\r//g;1,/^\$/d'>file; cmp file \$FILES/tar/tar.tar && echo yes" \
+  'yes\n' '' 'GET /tar/tar.tar HTTP/1.1\r\n\r\n' 
+rm -f file
+
+testcmd "mime type" \
+  '"$FILES" | tr A-Z a-z | sed -n "s/\r//g;s/^content-type: //p"' "application/x-tar\n" "" \
+  'GET /tar/tar.tar HTTP/1.1\r\n\r\n' 
+
diff --git a/tests/ifconfig.test b/tests/ifconfig.test
index ca8ca89..dcecc16 100755
--- a/tests/ifconfig.test
+++ b/tests/ifconfig.test
@@ -19,6 +19,8 @@
 #    outfill|keepalive INTEGER - SLIP analog dialup line quality monitoring
 #    metric INTEGER - added to Linux 0.9.10 with comment "never used", still true
 
+#testing "name" "command" "result" "infile" "stdin"
+
 [ -f testing.sh ] && . testing.sh
 
 if [ "$(id -u)" -ne 0 ]
@@ -28,10 +30,8 @@
   exit
 fi
 
-#testing "name" "command" "result" "infile" "stdin"
-
 # Add a dummy interface to test with
-modprobe dummy 2>/dev/null
+modprobe dummy >/dev/null 2>&1
 if ! ifconfig dummy0 up 2>/dev/null
 then
   echo "$SHOWSKIP: ifconfig dummy0 up failed"
@@ -39,38 +39,31 @@
   exit
 fi
 
-# Test Description: Disable the dummy0 interface
 # Results Expected: After calling ifconfig, no lines with dummy0 are displayed
-testing "dummy0 down and if config /-only" \
-"ifconfig dummy0 down && ifconfig | grep dummy | wc -l" \
-"0\n" "" ""
+testing "Disable the dummy0 interface" \
+  "ifconfig dummy0 down && ifconfig | grep dummy | wc -l" "0\n" "" ""
 
-# Test Description: Enable the dummy0 interface
 # Results Expected: After calling ifconfig, one line with dummy0 is displayed
-testing "dummy0 up" \
-"ifconfig dummy0 up && ifconfig dummy0 | grep dummy | wc -l" \
-"1\n" "" ""
+testing "Enable the dummy0 interface" \
+  "ifconfig dummy0 up && ifconfig dummy0 | grep dummy | wc -l" "1\n" "" ""
 
-# Test Description: Set the ip address of the dummy0 interface
 # Results Expected: After calling ifconfig dummy0, one line displays the ip
 #                   address selected
-testing "dummy0 10.240.240.240" \
-"ifconfig dummy0 10.240.240.240 && ifconfig dummy0 | grep 10\.240\.240\.240 | wc -l" \
-"1\n" "" ""
+testing "Set the ip address of the dummy0 interface" \
+  "ifconfig dummy0 10.240.240.240 && ifconfig dummy0 | grep 10\.240\.240\.240 | wc -l" \
+  "1\n" "" ""
 
-# Test Description: Change the netmask to the interface
 # Results Expected: After calling ifconfig dummy0, one line displays the
 #                   netmask selected
-testing "dummy0 netmask 255.255.240.0" \
-"ifconfig dummy0 netmask 255.255.240.0 && ifconfig dummy0 | grep 255\.255\.240\.0 | wc -l" \
-"1\n" "" ""
+testing "Change the netmask to the interface" \
+  "ifconfig dummy0 netmask 255.255.240.0 && ifconfig dummy0 | grep 255\.255\.240\.0 | wc -l" \
+  "1\n" "" ""
 
-# Test Description: Change the broadcast address to the interface
 # Results Expected: After calling ifconfig dummy0, one line displays the
 #                   broadcast address selected
-testing "dummy0 broadcast 10.240.240.255" \
-"ifconfig dummy0 broadcast 10.240.240.255 && ifconfig dummy0 | grep 10\.240\.240\.255 | wc -l" \
-"1\n" "" ""
+testing "Change the broadcast address to the interface" \
+  "ifconfig dummy0 broadcast 10.240.240.255 && ifconfig dummy0 | grep 10\.240\.240\.255 | wc -l" \
+  "1\n" "" ""
 
 # Test Description: Revert to the default ip address
 # Results Expected: After calling ifconfig dummy0, there are no lines
diff --git a/tests/ls.test b/tests/ls.test
index 4856da5..fad27d3 100755
--- a/tests/ls.test
+++ b/tests/ls.test
Binary files differ
diff --git a/tests/lsattr.test b/tests/lsattr.test
index 63d9ee9..f2beef5 100644
--- a/tests/lsattr.test
+++ b/tests/lsattr.test
@@ -31,12 +31,12 @@
 NOSPACE=1 testing "-lv file" "lsattr -lv file | clean" "_ file No_Atime\n" "" ""
 
 # You need at least Linux 4.5 plus file system support for project ids.
-lsattr -p file >/dev/null 2>&1 || SKIPNEXT=1
-NOSPACE=1 testing "-p file" "lsattr -p file | clean" "_ $_A file\n" "" ""
-lsattr -p file >/dev/null 2>&1 || SKIPNEXT=1
-NOSPACE=1 testing "-lp file" "lsattr -lp file | clean" "_ file No_Atime\n" "" ""
-lsattr -p file >/dev/null 2>&1 || SKIPNEXT=1
-NOSPACE=1 testing "-vp file" "lsattr -vp file | clean" "_ _ $_A file\n" "" ""
+lsattr -p file >/dev/null 2>&1 || SKIP=999
+  NOSPACE=1 testing "-p file" "lsattr -p file | clean" "_ $_A file\n" "" ""
+  NOSPACE=1 testing "-lp file" "lsattr -lp file | clean" "_ file No_Atime\n" \
+    "" ""
+  NOSPACE=1 testing "-vp file" "lsattr -vp file | clean" "_ _ $_A file\n" "" ""
+SKIP=0
 
 chattr -AacDdijsStTu file && cd ..
 rm -rf dir
diff --git a/tests/modinfo.test b/tests/modinfo.test
index 261acfd..b860a3e 100644
--- a/tests/modinfo.test
+++ b/tests/modinfo.test
@@ -17,9 +17,9 @@
 testcmd "missing" "missing 2>&1" "modinfo: missing: not found\n" "" ""
 
 # Find some modules to work with.
-MODULE_PATH1=$(find $MODULE_ROOT/lib/modules -name *.ko | head -1 2>/dev/null)
+MODULE_PATH1=$(find $MODULE_ROOT/lib/modules/ -name *.ko | head -1 2>/dev/null)
 MODULE1=$(basename -s .ko $MODULE_PATH1)
-MODULE_PATH2=$(find $MODULE_ROOT/lib/modules -name *.ko | head -2 | tail -1 2>/dev/null)
+MODULE_PATH2=$(find $MODULE_ROOT/lib/modules/ -name *.ko | head -2 | tail -1 2>/dev/null)
 MODULE2=$(basename -s .ko $MODULE_PATH2)
 DASH_MODULE=$(basename -s .ko \
   $(find $MODULE_ROOT/lib/modules -name *-*.ko | tail -1 2>/dev/null))
diff --git a/tests/patch.test b/tests/patch.test
index 5cc6001..9f44e07 100755
--- a/tests/patch.test
+++ b/tests/patch.test
@@ -4,6 +4,14 @@
 
 #testing "name" "command" "result" "infile" "stdin"
 
+testing "dry run doesn't create file" \
+  "patch --dry-run >/dev/null && [ ! -e bork ] && echo yes" "yes\n" "" "
+--- /dev/null
++++ bork
+@@ -0,0 +1,1 @@
++one
+"
+
 testing "create file" "patch >/dev/null && cat bork" "one\ntwo\nthree\n" "" "
 --- /dev/null
 +++ bork
@@ -12,6 +20,7 @@
 +two
 +three
 "
+
 testing "insert in middle" "patch > /dev/null && cat bork" \
   "one\nfour\ntwo\nthree\n" "" "
 --- bork
@@ -81,10 +90,29 @@
 testing "quoted name" "patch > /dev/null && cat 'fruit bat'" \
   "hello\n" "" '
 --- /dev/null
-+++ "fruit bat"
++++ "fruit ba\164"
 @@ -0,0 +1 @@
 +hello
 '
+
+testing "bad quote" "patch 2>&1" $'patch: bad "filename\n' "" '--- "filename'
+
+testing "dry run doesn't delete file" \
+  "patch --dry-run > /dev/null && [ -e 'fruit bat' ] && echo yes" "yes\n" "" '
+--- "fruit bat"
++++ /dev/null
+@@ -1 +0,0 @@
+-hello
+'
+
+testing "delete file" \
+  "patch > /dev/null && [ ! -e 'fruit bat' ] && echo yes" "yes\n" "" '
+--- "fruit bat"
++++ /dev/null
+@@ -1 +0,0 @@
+-hello
+'
+
 # todo bork bork2
 
 # We hit a bug, test the bugfix.
diff --git a/tests/printf.test b/tests/printf.test
index 30525c6..200e2d5 100755
--- a/tests/printf.test
+++ b/tests/printf.test
@@ -7,78 +7,74 @@
 
 #testing "name" "command" "result" "infile" "stdin"
 
-# Disable shell builtin
-PRINTF="$(which printf)"
+# Note: must use "testcmd" not "testing" else it's testing the shell builtin.
 
-testing "text" "$PRINTF TEXT" "TEXT" "" ""
+testcmd "text" "TEXT" "TEXT" "" ""
 
 # TODO: we have to use \x1b rather than \e in the expectations because
 # the Mac is stuck on bash 3.2 which doesn't support \e. This can go
 # away when we have a usable toysh.
-testing "escapes" "$PRINTF 'one\ntwo\n\v\t\r\f\e\b\athree'" \
+testcmd "escapes" "'one\ntwo\n\v\t\r\f\e\b\athree'" \
   "one\ntwo\n\v\t\r\f\x1b\b\athree" "" ""
-testing "%b escapes" "$PRINTF %b 'one\ntwo\n\v\t\r\f\e\b\athree'" \
+testcmd "%b escapes" "%b 'one\ntwo\n\v\t\r\f\e\b\athree'" \
   "one\ntwo\n\v\t\r\f\x1b\b\athree" "" ""
 
-testing "null" "$PRINTF 'x\0y' | od -An -tx1" ' 78 00 79\n' "" ""
-testing "trailing slash" "$PRINTF 'abc\'" 'abc\' "" ""
-testing "octal" "$PRINTF ' \1\002\429\045x'" ' \001\002"9%x' "" ""
-testing "not octal" "$PRINTF '\9'" '\9' "" ""
-testing "hex" "$PRINTF 'A\x1b\x2B\x3Q\xa' | od -An -tx1" \
-  ' 41 1b 2b 03 51 0a\n' "" ""
-testing "%x" "$PRINTF '%x\n' 0x2a" "2a\n" "" ""
+testcmd "null" "'x\0y' | od -An -tx1" ' 78 00 79\n' "" ""
+testcmd "trailing slash" "'abc\'" 'abc\' "" ""
+testcmd "octal" "' \1\002\429\045x'" ' \001\002"9%x' "" ""
+testcmd "not octal" "'\9'" '\9' "" ""
+testcmd "hex" "'A\x1b\x2B\x3Q\xa' | od -An -tx1" ' 41 1b 2b 03 51 0a\n' "" ""
+testcmd "%x" "'%x\n' 0x2a" "2a\n" "" ""
 
-testing "%d 42" "$PRINTF %d 42" "42" "" ""
-testing "%d 0x2a" "$PRINTF %d 0x2a" "42" "" ""
-testing "%d 052" "$PRINTF %d 052" "42" "" ""
+testcmd "%d 42" "%d 42" "42" "" ""
+testcmd "%d 0x2a" "%d 0x2a" "42" "" ""
+testcmd "%d 052" "%d 052" "42" "" ""
+testcmd "%d none" "%d" "0" "" ""
+testcmd "%d null" "%d ''" "0" "" ""
 
-testing "%s width precision" \
-  "$PRINTF '%3s,%.3s,%10s,%10.3s' abcde fghij klmno pqrst" \
+testcmd "%s width precision" "'%3s,%.3s,%10s,%10.3s' abcde fghij klmno pqrst" \
   "abcde,fgh,     klmno,       pqr" "" ""
 
 # posix: "The format operand shall be reused as often as necessary to satisfy
 # the argument operands."
 
-testing "extra args" "$PRINTF 'abc%s!%ddef\n' X 42 ARG 36" \
+testcmd "extra args" "'abc%s!%ddef\n' X 42 ARG 36" \
 	"abcX!42def\nabcARG!36def\n" "" ""
 
-testing "'%3c'" "$PRINTF '%3c' x" "  x" "" ""
-testing "'%-3c'" "$PRINTF '%-3c' x" "x  " "" ""
-testing "'%+d'" "$PRINTF '%+d' 5" "+5" "" ""
+testcmd "'%3c'" "'%3c' x" "  x" "" ""
+testcmd "'%-3c'" "'%-3c' x" "x  " "" ""
+testcmd "'%+d'" "'%+d' 5" "+5" "" ""
 
-
-testing "'%5d%4d' 1 21 321 4321 54321" \
-  "$PRINTF '%5d%4d' 1 21 321 4321 54321" "    1  21  321432154321   0" "" ""
-testing "'%c %c' 78 79" "$PRINTF '%c %c' 78 79" "7 7" "" ""
-testing "'%d %d' 78 79" "$PRINTF '%d %d' 78 79" "78 79" "" ""
-testing "'%f %f' 78 79" "$PRINTF '%f %f' 78 79" \
-  "78.000000 79.000000" "" ""
-testing "'f f' 78 79" "$PRINTF 'f f' 78 79 2>/dev/null" "f f" "" ""
-testing "'%i %i' 78 79" "$PRINTF '%i %i' 78 79" "78 79" "" ""
-testing "'%o %o' 78 79" "$PRINTF '%o %o' 78 79" "116 117" "" ""
-testing "'%u %u' 78 79" "$PRINTF '%u %u' 78 79" "78 79" "" ""
-testing "'%u %u' -1 -2" "$PRINTF '%u %u' -1 -2" \
+testcmd "'%5d%4d' 1 21 321 4321 54321" \
+  "'%5d%4d' 1 21 321 4321 54321" "    1  21  321432154321   0" "" ""
+testcmd "'%c %c' 78 79" "'%c %c' 78 79" "7 7" "" ""
+testcmd "'%d %d' 78 79" "'%d %d' 78 79" "78 79" "" ""
+testcmd "'%f %f' 78 79" "'%f %f' 78 79" "78.000000 79.000000" "" ""
+testcmd "'f f' 78 79" "'f f' 78 79 2>/dev/null" "f f" "" ""
+testcmd "'%i %i' 78 79" "'%i %i' 78 79" "78 79" "" ""
+testcmd "'%o %o' 78 79" "'%o %o' 78 79" "116 117" "" ""
+testcmd "'%u %u' 78 79" "'%u %u' 78 79" "78 79" "" ""
+testcmd "'%u %u' -1 -2" "'%u %u' -1 -2" \
   "18446744073709551615 18446744073709551614" "" ""
-testing "'%x %X' 78 79" "$PRINTF '%x %X' 78 79" "4e 4F" "" ""
-testing "'%g %G' 78 79" "$PRINTF '%g %G' 78 79" "78 79" "" ""
-testing "'%s %s' 78 79" "$PRINTF '%s %s' 78 79" "78 79" "" ""
+testcmd "'%x %X' 78 79" "'%x %X' 78 79" "4e 4F" "" ""
+testcmd "'%g %G' 78 79" "'%g %G' 78 79" "78 79" "" ""
+testcmd "'%s %s' 78 79" "'%s %s' 78 79" "78 79" "" ""
 
-testing "%.s acts like %.0s" "$PRINTF %.s_ 1 2 3 4 5" "_____" "" ""
-testing "corner case" "$PRINTF '\\8'" '\8' '' ''
+testcmd "%.s acts like %.0s" "%.s_ 1 2 3 4 5" "_____" "" ""
+testcmd "corner case" "'\\8'" '\8' '' ''
 
 # The posix spec explicitly specifies inconsistent behavior,
 # so treating the \0066 in %b like the \0066 not in %b is wrong because posix.
-testing "printf posix inconsistency" "$PRINTF '\\0066-%b' '\\0066'" "\x066-6" \
+testcmd "posix inconsistency" "'\\0066-%b' '\\0066'" "\x066-6" "" ""
+
+testcmd '\x' "'A\x1b\x2B\x3Q\xa' | od -An -tx1" " 41 1b 2b 03 51 0a\n" \
   "" ""
 
-testing "printf \x" "$PRINTF 'A\x1b\x2B\x3Q\xa' | od -An -tx1" \
-  " 41 1b 2b 03 51 0a\n" "" ""
-
-testing "printf \c" "$PRINTF 'one\ctwo'" "one" "" ""
+testcmd '\c' "'one\ctwo'" "one" "" ""
 
 # An extra leading 0 is fine for %b, but not as a direct escape, for some
 # reason...
-testing "printf octal %b" "$PRINTF '\0007%b' '\0007' | xxd -p" "003707\n" "" ""
+testcmd "octal %b" "'\0007%b' '\0007' | xxd -p" "003707\n" "" ""
 
 # Unlike echo, printf errors out on bad hex.
 testcmd "invalid hex 1" "'one\xvdtwo' 2>/dev/null || echo err" "oneerr\n" "" ""
diff --git a/tests/readlink.test b/tests/readlink.test
index cc728db..92e80e8 100755
--- a/tests/readlink.test
+++ b/tests/readlink.test
@@ -31,13 +31,17 @@
 testing "-f link->link (recursive)" \
   "readlink -f link 2>/dev/null || echo yes" "yes\n" "" ""
 
-testing "-q notlink" "readlink -q file || echo yes" "yes\n" "" ""
-testing "-q link" "readlink -q link && echo yes" "yes\n" "" ""
+testing "-q notlink" "readlink -q file 2>&1 || echo yes" "yes\n" "" ""
+testing "-q link" "readlink -q link && echo yes" "link\nyes\n" "" ""
 testing "-q notfound" "readlink -q notfound || echo yes" "yes\n" "" ""
 testing "-e found" "readlink -e file" "$APWD/file\n" "" ""
 testing "-e notfound" \
   "readlink -e notfound 2>/dev/null || echo yes" "yes\n" "" ""
 testing "-nf ." "readlink -nf ." "$APWD" "" ""
+# -n means no newline at _end_. I.E. on last argument.
+toyonly testcmd '-nf multiple args' '-n link link' "link\nlink" '' ''
+testcmd '-nz' '-nz link' 'link' '' ''
+testcmd '-z' '-z link' 'link\0' '' ''
 
 mkdir sub &&
 ln -s . here &&
@@ -51,7 +55,8 @@
   "readlink -f /dev/null/file 2>/dev/null || echo yes" "yes\n" "" ""
 testing "-m missing/dir" "readlink -m sub/two/three" "$APWD/sub/two/three\n" "" ""
 testing "-m missing/../elsewhere" "readlink -m sub/two/../../three" "$APWD/three\n" "" ""
-testing "-m file/dir" "readlink -m sub/bang/two 2>/dev/null || echo err" "err\n" "" ""
+# TODO: host bug? That's not missing, that's "cannot exist".
+toyonly testing "-m file/dir" "readlink -m sub/bang/two 2>/dev/null || echo err" "err\n" "" ""
 rm link
 ln -sf / link || exit 1
 testing "-f link->/" "readlink -e link/dev" "/dev\n" "" ""
diff --git a/tests/realpath.test b/tests/realpath.test
index c42fd43..a768ff2 100755
--- a/tests/realpath.test
+++ b/tests/realpath.test
@@ -5,35 +5,62 @@
 #testing "name" "command" "result" "infile" "stdin"
 
 TOP="$(readlink -f .)"
+export PWD
+
+touch file
+mkdir -p one/two/three
+ln -s ./one uno
+ln -s one/two dos
 
 testcmd '' '.' "$TOP\n" '' ''
-#testcmd '-z' '-z . | tr "\0" X' "${TOP}X" '' ''
-touch file
+testcmd 'missing' 'missing' "$TOP/missing\n" '' ''
+testcmd 'missing2' 'missing/sub 2>/dev/null || echo err' 'err\n' '' ''
+testcmd '-z' '-z . | tr "\0" X' "${TOP}X" '' ''
 testcmd 'file' 'file' "$TOP/file\n" '' ''
-mkdir -p one/two/three
 testcmd 'dir' 'one/two/three' "$TOP/one/two/three\n" '' ''
-#testcmd '--relative-to' '. --relative-to=one/two/three' '../../..\n' '' ''
-#testcmd '--relative-base' 'one one/two one/two/three --relative-base=one/two' \
-#  "$TOP/one\n.\nthree\n" '' ''
-#testcmd '--relative-base stomps --relative-to' \
-#  '--relative-to=.. --relative-base=one/two one' "$TOP/one\n" '' ''
+testcmd '--relative-to' '. --relative-to=one/two/three' '../../..\n' '' ''
+testcmd '--relative-to2' \
+  '-m --relative-to=missing/that/ uno/../dos/linux/../../bingeley/bongeley/beep' \
+  '../../one/bingeley/bongeley/beep\n' '' ''
+testcmd '--relative-to3' '-m walrus --relative-to walrus' '.\n' '' ''
+testcmd '--relative-to4' '"$PWD" --relative-to one' '..\n' '' ''
+testcmd '--relative-to5' '--relative-to "$PWD" one' 'one\n' '' ''
+testcmd 'relative-to missing' \
+  '--relative-to nothing/potato . 2>/dev/null || echo fail' 'fail\n' '' ''
+testcmd 'relative-to missing -m' \
+  '-m --relative-to nothing/potato .' '../..\n' '' ''
+testcmd '--relative-base' 'one one/two one/two/three --relative-base=one/two' \
+  "$TOP/one\n.\nthree\n" '' ''
+testcmd '--relative-base stomps --relative-to' \
+  '--relative-to=.. --relative-base=one/two one' "$TOP/one\n" '' ''
+testcmd '-m with relative-base1' '-m --relative-base wurble wurble/poing' \
+  'poing\n' '' ''
+testcmd '-m with relative-base2' '-sm --relative-base wurble .' "$PWD\n" '' ''
+testcmd '-m with relative-base3' '-m --relative-base wurble wurble wurble/' \
+  '.\n.\n' '' ''
 testcmd 'missing defaults to -m' 'missing' "$TOP/missing\n" '' ''
 testcmd 'missing -e' '-e missing 2>/dev/null || echo ok' 'ok\n' '' ''
+testcmd '-L' '-L dos/../one' "$TOP/one\n" '' ''
+
+# -s vs -L
+ln -s .. parent
+testcmd "-s isn't L" '-s --relative-to=. parent' 'parent\n' '' ''
+testcmd "-L isn't s" '-L --relative-to=. parent' '..\n' '' ''
 
 # The -s tests use $PWD instead of $TOP because symlinks in path _to_ here
 # should not be resolved either. The shell exports $PWD: use it.
-ln -s ./one uno
-#testcmd '-s' '-s uno/two' "$PWD/uno/two\n" '' ''
-ln -s one/two dos
-#testcmd '-s link/..' '-es dos/three' "$PWD/dos/three\n" '' ''
-#testcmd '-s .. eats symlink' '-s dos/..' "$PWD\n" '' ''
+testcmd '-s' '-s uno/two' "$PWD/uno/two\n" '' ''
+testcmd '-s link/..' '-es dos/three' "$PWD/dos/three\n" '' ''
+testcmd '-s .. eats symlink' '-s dos/..' "$PWD\n" '' ''
 # In toybox this test is consistent with the previous one
-#toyonly testing '-s .. eats symlink in $PWD' \
-#  'cd dos && realpath -s ..' "$PWD\n" '' ''
+toyonly testing '-s .. eats symlink in $PWD' \
+  'cd dos && realpath -s ..' "$PWD\n" '' ''
 # Logically -es means the _symlink_ should exist, but match behavior...
 ln -s missing dangling
-#testcmd '-es dangling symlink' '-es dangling 2>/dev/null || echo ok' \
-#  'ok\n' '' ''
-#testcmd '-ms' '-ms dangling/../dos/../one/two' "$PWD/one/two\n" '' ''
+testcmd '-es dangling symlink' '-es dangling 2>/dev/null || echo ok' \
+  'ok\n' '' ''
+testcmd '-ms' '-ms dangling/../dos/../one/two' "$PWD/one/two\n" '' ''
 ln -s ../two/.. one/two/ichi
-#testcmd '-es' '-es one/two/ichi/two/ichi/two' "$PWD/one/two/ichi/two/ichi/two\n" '' ''
+testcmd '-es' '-es one/two/ichi/two/ichi/two' "$PWD/one/two/ichi/two/ichi/two\n" '' ''
+
+rm -rf file one uno dos
diff --git a/tests/sed.test b/tests/sed.test
index 5035478..ce35161 100755
--- a/tests/sed.test
+++ b/tests/sed.test
@@ -2,86 +2,82 @@
 
 #testing "name" "command" "result" "infile" "stdin"
 
-testing 'as cat' 'sed ""' "one\ntwo\nthree" "" "one\ntwo\nthree"
+testcmd 'as cat' '""' "one\ntwo\nthree" "" "one\ntwo\nthree"
 # This segfaults ubuntu 12.04's sed. No really.
-testing 'sed - - twice' 'sed "" - -' "hello\n" "" "hello\n"
-testing '-n' 'sed -n ""' "" "" "one\ntwo\nthree"
-testing '-n p' 'sed -n p' "one\ntwo\nthree" "" "one\ntwo\nthree"
-testing 'explicit pattern' 'sed -e p -n' "one\ntwo\nthree" "" \
-	"one\ntwo\nthree"
+testcmd '- - twice' '"" - -' "hello\n" "" "hello\n"
+testcmd '-n' '-n ""' "" "" "one\ntwo\nthree"
+testcmd '-n p' '-n p' "one\ntwo\nthree" "" "one\ntwo\nthree"
+testcmd 'explicit pattern' '-e p -n' "one\ntwo\nthree" "" "one\ntwo\nthree"
 
 # Exploring the wonders of sed addressing modes
-testing '' 'sed -n 1p' "one\n" "" "one\ntwo\nthree"
-testing '' 'sed 2p' "one\ntwo\ntwo\nthree" "" "one\ntwo\nthree"
-testing '' 'sed -n 2p' "two\n" "" "one\ntwo\nthree"
-testing '-n $p' 'sed -n \$p' "three" "" "one\ntwo\nthree"
-testing 'as cat #2' "sed -n '1,\$p'" "one\ntwo\nthree" "" "one\ntwo\nthree"
-testing 'no input means no last line' "sed '\$a boing'" "" "" ""
-testing '-n $,$p' 'sed -n \$,\$p' 'three' '' 'one\ntwo\nthree'
-testing '' 'sed -n 1,2p' "one\ntwo\n" "" "one\ntwo\nthree"
-testing '' 'sed -n 2,3p' "two\nthree" "" "one\ntwo\nthree"
-testing '' 'sed -n 2,1p' "two\n" "" "one\ntwo\nthree"
-testing '$ with 2 inputs' 'sed -n \$p - input' "four\n" "four\n" \
-	"one\ntwo\nthree"
-testing '' 'sed -n /two/p' "two\n" "" "one\ntwo\nthree"
-testing '' 'sed -n 1,/two/p' 'one\ntwo\n' '' 'one\ntwo\nthree'
-testing '' 'sed -n /one/,2p' 'one\ntwo\n' '' 'one\ntwo\nthree'
-testing '' 'sed -n 1,/one/p' 'one\ntwo\nthree' '' 'one\ntwo\nthree'
-testing '' 'sed -n /one/,1p' 'one\n' '' 'one\ntwo\nthree'
-testing 'sed -n /two/,$p' 'sed -n /two/,\$p' 'two\nthree' '' 'one\ntwo\nthree'
-
+testcmd '' '-n 1p' "one\n" "" "one\ntwo\nthree"
+testcmd '' '2p' "one\ntwo\ntwo\nthree" "" "one\ntwo\nthree"
+testcmd '' '-n 2p' "two\n" "" "one\ntwo\nthree"
+testcmd '-n $p' '-n \$p' "three" "" "one\ntwo\nthree"
+testcmd 'as cat #2' "-n '1,\$p'" "one\ntwo\nthree" "" "one\ntwo\nthree"
+testcmd 'no input means no last line' "'\$a boing'" "" "" ""
+testcmd '-n $,$p' '-n \$,\$p' 'three' '' 'one\ntwo\nthree'
+testcmd '' '-n 1,2p' "one\ntwo\n" "" "one\ntwo\nthree"
+testcmd '' '-n 2,3p' "two\nthree" "" "one\ntwo\nthree"
+testcmd '' '-n 2,1p' "two\n" "" "one\ntwo\nthree"
+testcmd '$ with 2 inputs' '-n \$p - input' "four\n" "four\n" "one\ntwo\nthree"
+testcmd '' '-n /two/p' "two\n" "" "one\ntwo\nthree"
+testcmd '' '-n 1,/two/p' 'one\ntwo\n' '' 'one\ntwo\nthree'
+testcmd '' '-n /one/,2p' 'one\ntwo\n' '' 'one\ntwo\nthree'
+testcmd '' '-n 1,/one/p' 'one\ntwo\nthree' '' 'one\ntwo\nthree'
+testcmd '' '-n /one/,1p' 'one\n' '' 'one\ntwo\nthree'
+testcmd '-n /two/,$p' '-n /two/,\$p' 'two\nthree' '' 'one\ntwo\nthree'
 
 # Fun with newlines!
-testing '' 'sed -n 3p' "three" "" "one\ntwo\nthree"
-testing 'prodigal newline' "sed -n '1,\$p' - input" \
+testcmd '' '-n 3p' "three" "" "one\ntwo\nthree"
+testcmd 'prodigal newline' "-n '1,\$p' - input" \
 	"one\ntwo\nthree\nfour\n" "four\n" "one\ntwo\nthree"
-testing 'Newline only added if further output' "sed -n 3p - input" "three" \
+testcmd 'Newline only added if further output' "-n 3p - input" "three" \
 	"four\n" "one\ntwo\nthree"
 
 # Fun with match delimiters and escapes
-testing 'match \t tab' "sed -n '/\t/p'" "\tx\n" "" "\tx\n"
-testing 'match t delim disables \t tab' "sed -n '\t\txtp'" "" "" "\tx\n"
-testing 'match t delim makes \t literal t' \
-	"sed -n '\t\txtp'" "tx\n" "" "tx\n"
-testing 'match n delim' "sed -n '\n\txnp'" "\tx\n" "" "\tx\n"
-testing 'match n delim disables \n newline' "sed -n '\n\nxnp'" "" "" "\nx\n"
-toyonly testing 'match \n literal n' "sed -n '\n\nxnp'" "nx\n" "" "nx\n"
-testing 'end match does not check starting match line' \
-	"sed -n '/two/,/two/p'" "two\nthree" "" "one\ntwo\nthree"
-testing 'end match/start match mixing number/letter' \
-	"sed -n '2,/two/p'" "two\nthree" "" "one\ntwo\nthree"
-testing 'num then regex' 'sed -n 2,/d/p' 'b\nc\nd\n' '' 'a\nb\nc\nd\ne\nf\n'
-testing 'regex then num' 'sed -n /b/,4p' 'b\nc\nd\n' '' 'a\nb\nc\nd\ne\nf\n'
-testing 'multiple regex address match' 'sed -n /on/,/off/p' \
+testcmd 'match \t tab' "-n '/\t/p'" "\tx\n" "" "\tx\n"
+testcmd 'match t delim disables \t tab' "-n '\t\txtp'" "" "" "\tx\n"
+testcmd 'match t delim makes \t literal t' "-n '\t\txtp'" "tx\n" "" "tx\n"
+testcmd 'match n delim' "-n '\n\txnp'" "\tx\n" "" "\tx\n"
+testcmd 'match n delim disables \n newline' "-n '\n\nxnp'" "" "" "\nx\n"
+toyonly testcmd 'match \n literal n' "-n '\n\nxnp'" "nx\n" "" "nx\n"
+testcmd 'end match does not check starting match line' \
+	"-n '/two/,/two/p'" "two\nthree" "" "one\ntwo\nthree"
+testcmd 'end match/start match mixing number/letter' \
+	"-n '2,/two/p'" "two\nthree" "" "one\ntwo\nthree"
+testcmd 'num then regex' '-n 2,/d/p' 'b\nc\nd\n' '' 'a\nb\nc\nd\ne\nf\n'
+testcmd 'regex then num' '-n /b/,4p' 'b\nc\nd\n' '' 'a\nb\nc\nd\ne\nf\n'
+testcmd 'multiple regex address match' '-n /on/,/off/p' \
 	'bone\nturtle\scoff\ntron\nlurid\noffer\n'  "" \
 	'zap\nbone\nturtle\scoff\nfred\ntron\nlurid\noffer\nbecause\n'
-testing 'regex address overlap' 'sed -n /on/,/off/p' "on\nzap\noffon\n" "" \
+testcmd 'regex address overlap' '-n /on/,/off/p' "on\nzap\noffon\n" "" \
 	'on\nzap\noffon\nping\noff\n'
-testing 'getdelim with nested [:blah:]' 'sed -n "sa\a[a[:space:]bc]*aXXagp"' \
+testcmd 'getdelim with nested [:blah:]' '-n "sa\a[a[:space:]bc]*aXXagp"' \
 	"ABXXCDXXEFXXGHXXIXX" "" "ABaaCDa EFaa aGHa a Ia "
-testing '[ in [[]' "sed 's@[[]@X@g'" "X" "" "["
-testing '[[] with ] as delimiter' "sed 's][[]]X]g'" "X" "" "["
-testing '[[] with [ as delimiter' "sed 's[\[\[][X['" "X" "" "["
+testcmd '[ in [[]' "'s@[[]@X@g'" "X" "" "["
+testcmd '[[] with ] as delimiter' "'s][[]]X]g'" "X" "" "["
+testcmd '[[] with [ as delimiter' "'s[\[\[][X['" "X" "" "["
 
 # gGhHlnNpPqrstwxy:=
 # s///#comment
 # abcdDi
 
-testing 'prodigaler newline' 'sed -e a\\ -e woo' 'one\nwoo\n' '' 'one'
-testing "aci" \
-	"sed -e '3a boom' -e '/hre/i bang' -e '3a whack' -e '3c bong'" \
+testcmd 'prodigaler newline' '-e a\\ -e woo' 'one\nwoo\n' '' 'one'
+testcmd "aci" "-e '3a boom' -e '/hre/i bang' -e '3a whack' -e '3c bong'" \
 	"one\ntwo\nbang\nbong\nboom\nwhack\nfour\n" "" \
 	"one\ntwo\nthree\nfour\n"
-testing "b loop" "sed ':woo;=;b woo' | head -n 5" '1\n1\n1\n1\n1\n' "" "X"
-testing "b skip" "sed -n '2b zap;d;:zap;p'" "two\n" "" "one\ntwo\nthree"
-testing "b end" "sed -n '2b;p'" "one\nthree" "" "one\ntwo\nthree"
-testing "c range" "sed '2,4c blah'" "one\nblah\nfive\nsix" "" \
+testcmd "b loop" "':woo;=;b woo' | head -n 5" '1\n1\n1\n1\n1\n' "" "X"
+testcmd "b skip" "-n '2b zap;d;:zap;p'" "two\n" "" "one\ntwo\nthree"
+testcmd "b end" "-n '2b;p'" "one\nthree" "" "one\ntwo\nthree"
+testcmd "c range" "'2,4c blah'" "one\nblah\nfive\nsix" "" \
 	"one\ntwo\nthree\nfour\nfive\nsix"
-testing "c {range}" "sed -e '2,4{c blah' -e '}'" \
-	"one\nblah\nblah\nblah\nfive\nsix" \
+testcmd "c {range}" "-e '2,4{c blah' -e '}'" "one\nblah\nblah\nblah\nfive\nsix"\
         "" "one\ntwo\nthree\nfour\nfive\nsix"
-testing "c multiple continuation" \
-	"sed -e 'c\\' -e 'two\\' -e ''" "two\n\n" "" "hello"
+testcmd "c multiple continuation" "-e 'c\\' -e 'two\\' -e ''" "two\n\n" "" \
+        "hello"
+testcmd 'multiline continuations' '-e c\\ -e line1\\ -e line2' 'line1\nline2\n'\
+        '' 'one\n'
 toyonly testing "c empty continuation" "sed -e 'c\\'" "\n" "" "hello"
 testing "D further processing depends on whether line is blank" \
 	"sed -e '/one/,/three/{' -e 'i meep' -e'N;2D;}'" \
@@ -129,6 +125,9 @@
 	"one two three\nabcthreedef four five\nfive six seven\n" "" \
 	"one two three\nthree four five\nfive six seven\n"
 
+testcmd "interleave -e and -f" "-e 'a abc' -f input -e 'a ghi'" \
+  "hello\nabc\ndef\nghi\n" "a def" "hello\n"
+
 # Different ways of parsing line continuations
 
 testing "" "sed -e '1a\' -e 'huh'" "meep\nhuh\n" "" "meep"
@@ -162,11 +161,6 @@
 testing "not -s" "sed -n 1p input -" "one" "one" "two"
 testing "-s" "sed -sn 1p input -" "one\ntwo" "one\n" "two"
 
-#echo meep | sed/sed -e '1a\' -e 'huh'
-#echo blah | sed/sed -f <(echo -e "1a\\\\\nboom")
-#echo merp | sed/sed "1a\\
-#hello"
-
 testing "bonus backslashes" \
   "sed -e 'a \l \x\' -e \"\$(echo -e 'ab\\\nc')\"" \
   "hello\nl x\nab\nc\n" "" "hello\n"
@@ -175,18 +169,27 @@
 testing "end b with }" "sed -n '/START/{:a;n;/END/q;p;ba}'" "b\nc\n" \
   "" "a\nSTART\nb\nc\nEND\nd"
 
-testing '-z' 'sed -z "s/\n/-/g"' "a-b-c" "" "a\nb\nc"
+testcmd '-z' '-z "s/\n/-/g"' "a-b-c" "" "a\nb\nc"
+testcmd '-z N' '-z N' 'one\0two\0' '' 'one\0two\0'
+testcmd 'p noeol' '-z p' 'one\0one' '' 'one'
+testcmd '-z N noeol' '-z N' 'one\0two' '' 'one\0two'
+testcmd '-z S' "-z 'N;P'" 'one\0one\0two' '' 'one\0two'
+testcmd '-z D' "-z 'N;D'" 'two' '' 'one\0two'
+testcmd '-z G' "-z 'h;G'" 'one\0one' '' 'one'
+testcmd '-z H' "-z 'H;g'" '\0one' '' 'one'
+toyonly testcmd '-z x NOEOL' '-z ax' 'abc\0x\0def\0x\0' '' 'abc\0def'
+testcmd 's after NUL' 's/t/x/' 'one\0xwo' '' 'one\0two'
+testcmd '^ not trigger after NUL' 's/^t/x/' 'one\0two' '' 'one\0two'
 
 # toybox handling of empty capturing groups broke minjail. Check that we
 # correctly replace an empty capturing group with the empty string:
-testing '\n with empty capture' \
-    'sed -E "s/(ARM_)?(NR_)([a-z]*) (.*)/\1\2\3/"' "NR_read" "" "NR_read foo"
+testcmd '\n with empty capture' \
+    '-E "s/(ARM_)?(NR_)([a-z]*) (.*)/\1\2\3/"' "NR_read" "" "NR_read foo"
 # ...but also that we report an error for a backreference to a group that
 # isn't in the pattern:
-testing '\n too high' \
-    'sed -E "s/(.*)/\2/p" 2>/dev/null || echo OK' "OK\n" "" "foo"
+testcmd '\n too high' '-E "s/(.*)/\2/p" 2>/dev/null || echo OK' "OK\n" "" "foo"
 
-toyonly testing 's///x' 'sed "s/(hello )?(world)/\2/x"' "world" "" "hello world"
+toyonly testcmd 's///x' '"s/(hello )?(world)/\2/x"' "world" "" "hello world"
 
 # Performance test
 X=x; Y=20; while [ $Y -gt 0 ]; do X=$X$X; Y=$(($Y-1)); done
@@ -195,9 +198,21 @@
   '138c1fa7c3f64186203b0192fb4abdb33cb4e98a  -\n' '' "$X\n"
 unset X Y
 
-testing "w doesn't blank" "sed -e 'w one' -e 'w one' -e d; cat one" \
-  'hello\nhello\n' '' 'hello\n'
+testcmd "w doesn't blank" "-e 'w one' -e 'w one' -e d; cat one" \
+        'hello\nhello\n' '' 'hello\n'
 
-testing 's i and I' 'sed s/o/0/ig' "f00l F00L" "" "fool FOOL"
+testcmd 's i and I' 's/o/0/ig' "f00l F00L" "" "fool FOOL"
+
+testcmd 's l ignores posix' "-n 'N;l'" 'one\\ntwo$\n' '' 'one\ntwo\n'
+testcmd 's l loses missing newline' "-n 'N;l'" 'one\\ntwo$\n' '' 'one\ntwo'
+testcmd 's -z l' "-zn 'N;l'" 'one\\000two$\0' '' 'one\0two\0'
+testcmd 's -z l missing newline' "-zn 'N;l'" 'one\\000two$\0' '' 'one\0two'
+
+testcmd 'count match' '"s/./&X/4"' '0123X45\n' '' '012345\n'
 
 # -i with $ last line test
+
+#echo meep | sed/sed -e '1a\' -e 'huh'
+#echo blah | sed/sed -f <(echo -e "1a\\\\\nboom")
+#echo merp | sed/sed "1a\\
+#hello"
diff --git a/tests/seq.test b/tests/seq.test
index 05d9b1e..6b80e6a 100755
--- a/tests/seq.test
+++ b/tests/seq.test
@@ -73,4 +73,6 @@
 testing "INT_MIN" "seq -2147483648 -2147483647" "-2147483648\n-2147483647\n"\
   "" ""
 
+# macOS doesn't include a timeout(1), nor a good alternative.
+skipnot [ "$(uname)" != "Darwin" ]
 testing "fast path" "timeout 10 seq 10000000 > /dev/null" "" "" ""
diff --git a/tests/sh.test b/tests/sh.test
index 9cfa9fd..0cc16b9 100644
--- a/tests/sh.test
+++ b/tests/sh.test
@@ -57,7 +57,7 @@
 
 shxpect "prompt and exit" I$'exit\n'
 shxpect "prompt and echo" I$'echo hello\n' O$'hello\n' E"$P"
-shxpect "redirect err" I$'echo > /dev/full\n' E E"$P"
+shxpect "redirect err" I$'echo > /dev/full\n' E E"$P" X1
 shxpect "wait for <(exit)" I$'cat <(echo hello 1>&2)\n' E$'hello\n' E"$P"
 
 # Test the sh -c stuff before changing EVAL
@@ -79,29 +79,13 @@
 testing '(subshell)' '$SH -c "(echo hello)"' 'hello\n' '' ''
 testing 'syntax' '$SH -c "if true; then echo hello | fi" 2>/dev/null || echo x'\
   'x\n' '' ''
+testing 'syntax2' '$SH -c "for;i 0" 2>&1 | { grep -qi syntax && echo yes; }' \
+  'yes\n' '' ''
 
 # The bash man page is lying when it says $_ starts with an absolute path.
-ln -s $(which $SH) bash
+ln -s "$(which $SH)" bash
 testing 'non-absolute $_' "./bash -c 'echo \$_'" './bash\n' '' ''
 rm bash
-testing '$_ with functions' 'true; x(){ echo $_;}; x abc; echo $_' \
-  'true\nabc\n' '' ''
-
-shxpect '$_ preserved on assignment error' I$'true hello; a=1 b=2 c=${}\n' \
-  E E"$P" I$'echo $_\n' O$'hello\n'
-shxpect '$_ preserved on prefix error' I$'true hello; a=1 b=2 c=${} true\n' \
-  E E"$P" I$'echo $_\n' O$'hello\n'
-shxpect '$_ preserved on exec error' I$'true hello; ${}\n' \
-  E E"$P" I$'echo $_\n' O$'hello\n'
-shxpect '$_ abspath on exec' I$'env | grep ^_=\n' O$'_=/usr/bin/env\n'
-testing '$_ literal after exec' 'env >/dev/null; echo $_' 'env\n' '' ''
-shxpect '$_ no path for builtin' I$'true; echo $_\n' O$'true\n'
-testing 'prefix is local for builtins' 'abc=123; abc=def unset abc; echo $abc' \
-  '123\n' '' ''
-testing 'prefix localizes magic vars' \
-  'SECONDS=123; SECONDS=345 true; echo $SECONDS' '123\n' '' ''
-shxpect 'body evaluated before variable exports' I$'a=x${} y${}\n' RE'y${}'
-testing '$NOTHING clears $_' 'true; $NOTHING; echo $_' '\n' '' ''
 
 testing 'exec exitval' "$SH -c 'exec echo hello' && echo \$?" "hello\n0\n" "" ""
 testing 'simple script' '$SH input' 'input\n' 'echo $0' ''
@@ -131,12 +115,34 @@
 #  "{ \$SH -c 'X=\${a?blah} > walroid';ls walroid;} 2>/dev/null" '' '' ''
 testing "lineno" "$SH input" "5 one\n6 one\n5 two\n6 two\n" \
   '#!/bin/bash\n\nfor i in one two\ndo\n  echo $LINENO $i\n  echo $LINENO $i\ndone\n' ""
-testing "eval0" "sh -c 'eval echo \$*' one two three" "two three\n" "" ""
+testing "eval0" "$SH -c 'eval echo \$*' one two three" "two three\n" "" ""
 
 #########################################################################
 # Change EVAL to call sh -c for us, using "bash" explicitly for the host.
-export EVAL="$SH -c"
+export EVAL="timeout 10 $SH -c"
 
+testing 'trailing $ is literal' 'echo $' '$\n' '' ''
+# TODO testing 'empty +() is literal' 'echo +()' '+()\n' '' ''
+shxpect 'queued work after HERE' I$'<<0;echo hello\n' E"> " I$'0\n' O$'hello\n'
+shxpect '$_ preserved on assignment error' I$'true hello; a=1 b=2 c=${}\n' \
+  E E"$P" I$'echo $_\n' O$'hello\n'
+shxpect '$_ preserved on prefix error' I$'true hello; a=1 b=2 c=${} true\n' \
+  E E"$P" I$'echo $_\n' O$'hello\n'
+shxpect '$_ preserved on exec error' I$'true hello; ${}\n' \
+  E E"$P" I$'echo $_\n' O$'hello\n'
+shxpect '$_ abspath on exec' I$'env | grep ^_=\n' O$'_=/usr/bin/env\n'
+testing '$_ literal after exec' 'env >/dev/null; echo $_' 'env\n' '' ''
+shxpect '$_ no path for builtin' I$'true; echo $_\n' O$'true\n'
+testing 'prefix is local for builtins' 'abc=123; abc=def unset abc; echo $abc' \
+  '123\n' '' ''
+testing 'prefix localizes magic vars' \
+  'SECONDS=123; SECONDS=345 true; echo $SECONDS' '123\n' '' ''
+shxpect 'body evaluated before variable exports' I$'a=x${} y${}\n' RE'y${}' X1
+testing '$NOTHING clears $_' 'true; $NOTHING; echo $_' '\n' '' ''
+testing 'assignment with redirect is persistent, not prefix' \
+  'ABC=DEF > potato && rm potato && echo $ABC' 'DEF\n' '' ''
+testing '$_ with functions' 'true; x(){ echo $_;}; x abc; echo $_' \
+  'true\nabc\n' '' ''
 
 mkdir -p one/two/three
 testing 'cd in renamed dir' \
@@ -211,6 +217,8 @@
   'ana a\n' '' ''
 toyonly testing '${x#utf8}' 'x=aそcde; echo ${x##a?c}' 'de\n' '' ''
 testing '${x%y}' 'x=potato; echo ${x%t*o} ${x%%t*o}' 'pota po\n' '' ''
+testing 'x=${x%y}' 'x=potato; x=${x%t*o}; echo $x' 'pota\n' '' ''
+testing 'x=${x//y}' 'x=potato; x=${x//ta}; echo $x' 'poto\n' '' ''
 testing '${x^y}' 'x=aaaaa; echo ${x^a}' 'Aaaaa\n' '' ''
 testing '${x^^y}' 'x=abccdec; echo ${x^^c}; x=abcdec; echo ${x^^c}' \
   'abCCdeC\nabCdeC\n' '' ''
@@ -222,19 +230,48 @@
 touch www
 testing 'wildcards' 'echo w[v-x]w w[x-v]w abc/*/ghi' \
   'www w[x-v]w abc/def/ghi\n' '' ''
+testing 'hidden wildcards' \
+  'touch .abc abc && echo *bc && echo and && echo .*bc' \
+  'abc\nand\n.abc\n' '' ''
 
 testing "backtick1" 'x=fred; echo `echo $x`' 'fred\n' "" ""
 testing "backtick2" 'x=fred; echo `x=y; echo $x`; echo $x' 'y\nfred\n' "" ""
 testing '$(( ) )' 'echo ab$((echo hello) | tr e x)cd' "abhxllocd\n" "" ""
-SKIPNEXT=1 testing '$((x=y)) lifetime' 'a=boing; echo $a $a$((a=4))$a $a' 'boing boing44 4\n' '' ''
+((++SKIP)); testing '$((x=y)) lifetime' 'a=boing; echo $a $a$((a=4))$a $a' 'boing boing44 4\n' '' ''
 
 testing 'quote' "echo \"'\"" "'\n" "" ""
 
 testing "math" 'echo $((1+2))' '3\n' '' ''
-testing "[math]" 'echo $[1+2]' '3\n' '' ''
-testing "math prio" 'echo $((1+2*3**4))' '163\n' '' ''
+testing "[oldmath]" 'echo $[1+2]' '3\n' '' ''
+testing "math basic priority" 'echo $((1+2*3**4))' '163\n' '' ''
 testing "math paren" 'echo $(((1+2)*3))' '9\n' '' ''
 testing "math spaces" 'echo $(( ( 1 + 2 ) * 7 - 5 ** 2 ))' '-4\n' '' ''
+testing "((<)) isn't redirect" '((1<2)) </dev/null && echo yes' 'yes\n' '' ''
+testing "((>)) isn't redirect" '((1>2)) </dev/null || echo yes' 'yes\n' '' ''
+testing "((not math) )" '((echo hello) )' 'hello\n' '' ''
+testing "preincrement" 'echo $((++x)); echo $x' '1\n1\n' '' ''
+testing "preincrement vs prefix plus" 'echo $((+++x)); echo $x' '1\n1\n' '' ''
+testing "predecrement" 'echo $((--x)); echo $x' '-1\n-1\n' '' ''
+testing "predecrement vs prefix minus" 'echo $((---x)); echo $x' '1\n-1\n' '' ''
+testing "minus-minus-minus" 'echo $((x---7)); echo $x' '-7\n-1\n' '' ''
+testing "x---y is x-- -y not x- --y" 'x=1 y=1; echo $((x---y)) $x $y' '0 0 1\n'\
+  '' ''
+testing "nesting ? :" \
+  'for((i=0;i<8;i++)); do echo $((i&1?i&2?1:i&4?2:3:4));done' \
+  '4\n3\n4\n1\n4\n2\n4\n1\n' '' ''
+testing "inherited assignment suppression" 'echo $((0 ? (x++) : 2)); echo $x' \
+  "2\n\n" "" ""
+testing "boolean vs logical" 'echo $((2|4&&8))' '1\n' '' ''
+testing "&& vs || priority" \
+  'echo $((w++||x++&&y++||z++)) w=$w x=$x y=$y z=$z' \
+  '0 w=1 x=1 y= z=1\n' '' ''
+testing "|| vs && priority" \
+  'echo $((w++&&x++||y++&&z++)) w=$w x=$x y=$y z=$z' \
+  '0 w=1 x= y=1 z=\n' '' ''
+shxpect '/0' I$'echo $((1/0)); echo here\n' E E"$P" I$'echo $?\n' O$'1\n'
+shxpect '%0' I$'echo $((1%0)); echo here\n' E E"$P" I$'echo $?\n' O$'1\n'
+shxpect '/=0' I$'echo $((x/=0)); echo here\n' E E"$P" I$'echo $?\n' O$'1\n'
+shxpect '%=0' I$'echo $((x%=0)); echo here\n' E E"$P" I$'echo $?\n' O$'1\n'
 
 # Loops and flow control
 testing "case" 'for i in A C J B; do case "$i" in A) echo got A ;; B) echo and B ;; C) echo then C ;; *) echo default ;; esac; done' \
@@ -244,6 +281,8 @@
 testing "case newlines" \
   $'case i\n\nin\n\na) echo one\n\n;;\n\ni)\n\necho two\n\n;;\n\nesac' \
   "two\n" "" ""
+testing "case block" \
+  $'case X in\n  X) printf %s "X" || { echo potato;} ;;\nesac' 'X' '' ''
 testing 'loop in && ||' \
   'false && for i in a b c; do echo $i; done || echo no' 'no\n' '' ''
 testing "continue" 'for i in a b c; do for j in d e f; do echo $i $j; continue 2; done; done' \
@@ -318,6 +357,8 @@
 testing "IFS4" 'IFS=x; echo $(echo abx)y' "ab y\n" "" ""
 testing "IFS5" 'IFS=xy; for i in abcxdefyghi; do echo =$i=; done' \
   "=abc def ghi=\n" "" ""
+testing "curly bracket whitespace" 'for i in {$,} ""{$,}; do echo ="$i"=; done'\
+  '=$=\n=$=\n==\n' '' ''
 
 testing 'empty $! is blank' 'echo $!' "\n" "" ""
 testing '$! = jobs -p' 'true & [ $(jobs -p) = $! ] && echo yes' "yes\n" "" ""
@@ -428,6 +469,20 @@
   I$'$POTATO\n' E"> " I$'EOF\n' O$'$POTATO\n'
 testing 'here3' 'abc(){ cat <<< x"$@"yz;};abc one two "three  four"' \
   "xone two three  fouryz\n" "" ""
+testing 'here4' 'for i in one two three; do cat <<< "ab${i}de"; done' \
+  'abonede\nabtwode\nabthreede\n' '' ''
+testing 'here5' $'cat << EOF && cat << EOF2\nEOF2\nEOF\nEOF\nEOF2' \
+  'EOF2\nEOF\n' '' ''
+# Nothing is actually quoted, but there are quotes, therefore...
+testing 'here6' $'cat << EOF""\n$POTATO\nEOF' '$POTATO\n' '' ''
+# Not ambiguous when split, unlike <$FILENAME redirects
+testing 'here7' 'ABC="abc def"; cat <<< $ABC' 'abc def\n' '' ''
+# What does HERE expansion _not_ expand?
+testing 'here8' $'ABC="x y"\ncat << EOF\n~root/{"$ABC",def}\nEOF' \
+  '~root/{"x y",def}\n' '' ''
+# <<- eats leading tabs before expansion
+testing 'here9' $'A=$\'\\tone\'; cat <<- EOF\n$A\n\ttwo\nEOF' "\tone\ntwo\n" \
+  '' ''
 
 testing '${var}' 'X=abcdef; echo ${X}' 'abcdef\n' '' '' 
 testing '${#}' 'X=abcdef; echo ${#X}' "6\n" "" ""
@@ -563,6 +618,7 @@
   'func() { eval "echo one; echo \${?potato}; echo and" 2>/dev/null; echo plus;}; func; echo then' \
   'one\nplus\nthen\n' '' ''
 
+shxpect "functions need block" I$'x() echo;\n' RE'[Ss]yntax [Ee]rror' X2
 testing 'functions() {} in same PID' \
   '{ echo $BASHPID; chicken() { echo $BASHPID;}; chicken;} | sort -u | wc -l' '1\n' '' ''
 testing 'functions() () different PID' \
@@ -606,6 +662,28 @@
 testing 'NOP line clears $?' 'false;$NOTHING;echo $?' '0\n' '' ''
 testing 'run "$@"' 'false;"$@";echo $?' '0\n' '' ''
 
+# "Word splitting... not performed on the words between the [[ and ]]"
+testing '[[split1]]' 'A="1 -lt 2"; [[ $A ]] && echo yes' 'yes\n' '' ''
+testing '[[split2]]' 'A="2 -lt 1"; [[ $A ]] && echo yes' 'yes\n' '' ''
+testing '[[split3]]' \
+  'A="2 -lt 1"; [[ -e $A ]] && echo one; touch "$A" && [[ -e $A ]] && echo two'\
+  'two\n' '' ''
+rm -f '2 -lt 1'
+testing '[[split4]]' \
+  '[[ $(cat) == "a b" ]] <<< "a b" > potato && rm potato && echo ok' \
+  'ok\n' '' ''
+testing '[[split5]]' \
+  '[[ $(cat) == "a b" ]] < <(echo a b) > potato && rm potato && echo ok' \
+  'ok\n' '' ''
+# And token parsing leaking through: 1>2 is an error, 1 >2 is not
+testing '[[1>2]] is not a redirect' '[[ 1 >2 ]] || [ -e 2 ] || echo yup' \
+  'yup\n' '' ''
+testing "[[1 >0]] doesn't need that second space" \
+  '[[ 1 >0 ]] && { [ -e 2 ] || echo yup; }' 'yup\n' '' ''
+testing '[[1<2]] is alphabetical, not numeric' '[[ 123 < 19 ]] && echo yes' \
+  'yes\n' '' ''
+testing '[[~]]' '[[ ~ == $HOME ]] && echo yes' 'yes\n' '' ''
+
 # TODO finish variable list from shell init
 
 # $# $? $- $! $0  # $$
diff --git a/tests/skeleton.test b/tests/skeleton.test
new file mode 100755
index 0000000..0e54e76
--- /dev/null
+++ b/tests/skeleton.test
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+[ -f testing.sh ] && . testing.sh
+
+#testing "name" "command" "result" "infile" "stdin"
+
+# This is basically a test of lib/args.c argument parsing
+
+out() { printf 'Ran skeleton\n%sOther globals should start zeroed: 0' "$@";}
+testcmd "baseline " "" "$(out '')\n" "" ""
+testcmd "unknown" "-z |& grep -o Unknown" "Unknown\n" "" ""
+testcmd "passthrough args" "bingeley bongeley beep" \
+  "$(out 'optarg=bingeley\noptarg=bongeley\noptarg=beep\n')\n" "" ""
+testcmd "" "-a" "$(out 'flags=1\nSaw a\n')\n" "" ""
+testcmd "" "-b |& grep -o Missing" "Missing\n" "" ""
+testcmd "" "-b abc" "$(out 'flags=2\nb=abc\n')\n" "" ""
+testcmd "" "-c nondigit |& grep -o integer" "integer\n" "" ""
+testcmd "" "-c 123" "$(out 'flags=4\nc=123\n')\n" "" ""
+testcmd "" "-c 1m" "$(out 'flags=4\nc=1048576\n')\n" "" ""
+testcmd "" "-d one -d two -d 3,4" "$(out 'flags=8\nd=one\nd=two\nd=3,4\n')\n" \
+  "" ""
+testcmd "" "-e" "$(out 'flags=10\ne was seen 1 times\n')\n" "" ""
+testcmd "" "-ee -e -ae" "$(out 'flags=11\nSaw a\ne was seen 4 times\n')\n" \
+  "" ""
+testcmd "mixed" "123 -c 456 789" \
+  "$(out 'flags=4\nc=456\noptarg=123\noptarg=789\n')\n" "" ""
+# ala date -I
+testcmd "':;' short attached" "-fabc" "$(out 'flags=20\nf=abc\n')\n" "" ""
+testcmd "':;' short detached" "-f abc" "$(out 'flags=20\noptarg=abc\n')\n" "" ""
+testcmd "':;' long" "--lo abc" "$(out 'flags=20\noptarg=abc\n')\n" "" ""
+testcmd "':;' long=x" "--long=abc" "$(out 'flags=20\nf=abc\n')\n" "" ""
+testcmd "':;' long=" "--long=" "$(out 'flags=20\nf=\n')\n" "" ""
+testcmd "':;' long detached" "--long abc" "$(out 'flags=20\noptarg=abc\n')\n" "" ""
+# ala kill -stop
+testcmd "': ' short attached" "-gabc 2>/dev/null || echo yup" "yup\n" "" ""
+testcmd "': ' short detached" "-g abc" "$(out 'flags=40\ng=abc\n')\n" "" ""
+testcmd "': ' long" "--glong abc" "$(out 'flags=40\ng=abc\n')\n" "" ""
+testcmd "': ' long=x" "--gl=abc" "$(out 'flags=40\ng=abc\n')\n" "" ""
+testcmd "': ' long=" "--gl=" "$(out 'flags=40\ng=\n')\n" "" ""
+# ala unshare -fim
+testcmd "':; ' short attached" "-habc" "$(out 'flags=83\nSaw a\nb=c\n')\n" "" ""
+testcmd "':; ' short detached" "-h abc" "$(out 'flags=80\noptarg=abc\n')\n" "" ""
+testcmd "':; ' long=x" "--h=abc" "$(out 'flags=80\nh=abc\n')\n" "" ""
+testcmd "':; ' long=" "--h=" "$(out 'flags=80\nh=\n')\n" "" ""
+testcmd "':; ' long detached" "--hlong abc" "$(out 'flags=80\noptarg=abc\n')\n" "" ""
diff --git a/tests/sort.test b/tests/sort.test
index 5fe925e..dbb6ca0 100755
--- a/tests/sort.test
+++ b/tests/sort.test
@@ -104,6 +104,11 @@
 #  "toy-2.37.tar.gz\ntoy-3.4.tar.gz\ntoy-3.12.tar.gz\ntoy-4.16-rc2.tar.gz\ntoy-4.16.tar.gz\n" "" \
 #  "toy-3.12.tar.gz\ntoy-2.37.tar.gz\ntoy-3.4.tar.gz\ntoy-4.16-rc2.tar.gz\ntoy-4.16.tar.gz"
 
+testcmd "-c" "-c 2>&1 | grep -o [0-9]*" "3\n" "" "a\nb\na\nc"
+testcmd "-uc" "-uc 2>&1 | grep -o [0-9]*" "3\n" "" "a\nb\nb\nc"
+testcmd "-C 1" "-C || echo yes" "yes\n" "" "one\ntwo\nthree"
+testcmd "-C 2" "-C && echo yes" "yes\n" "" "a\nb\nc\n"
+
 optional SORT_FLOAT
 
 # not numbers < NaN < -infinity < numbers < +infinity
diff --git a/tests/tar.test b/tests/tar.test
old mode 100644
new mode 100755
index 034a3bf..e6487bd
--- a/tests/tar.test
+++ b/tests/tar.test
@@ -4,148 +4,161 @@
 
 #testing "name" "command" "result" "infile" "stdin"
 
-# For reproducibility: UTC and umask 0002
-
-OLDTZ="$TZ"
+# For reproducibility: TZ=UTC, umask 0002, override ownership and timestamp
 export TZ=utc
-OLDUMASK=$(umask)
 umask 0002
+TAR='tar c --owner root --group sys --mtime @1234567890'
 
 # 255 bytes, longest VFS name
 LONG=0123456789abcdef0123456789abcdef
 LONG=$LONG$LONG$LONG$LONG$LONG$LONG$LONG$LONG
 LONG=${LONG:1:255}
 
-# Reproducible tarballs: override ownership and timestamp.
-TAR='tar c --owner root --group root --mtime @1234567890'
+# We check both sha1sum (to ensure binary identical output) and list contents.
 
-# Different tars add variable trailing NUL padding (1024 bytes is just minimum)
-# so look at first N 512-byte frames when analyzing header content.
+# Check hash of first N 512 byte frames to ensure result is binary identical.
 function SUM()
 {
+  # Different tars add variable trailing NUL padding (1024 bytes is just
+  # minimum) so look at first N 512-byte frames when analyzing header content.
   tee save.dat | head -c $(($1*512)) | sha1sum | sed "s/ .*//"
 }
 
+# List tarball contents, converting variable tabs into one space
 function LST()
 {
   tar tv "$@" | sed 's/[ \t][ \t]*/ /g'
 }
 
+# Check that stored empty file is binary identical and decodes as expected.
 touch file
-testing "create file" "$TAR file | SUM 3" \
-  "fecaecba936e604bb115627a6ef4db7c7a3a8f81\n" "" ""
-
+testing "store file" "$TAR file | SUM 3" \
+  "2735f3a18d770dd0d7145d76108532f72bef9927\n" "" ""
 testing "pass file" "$TAR file | LST" \
-  "-rw-rw-r-- root/root 0 2009-02-13 23:31 file\n" "" ""
+  "-rw-rw-r-- root/sys 0 2009-02-13 23:31 file\n" "" ""
 
-# The kernel has two hardwired meaningful UIDs: 0 (root) and 65534 (nobody).
-# (Technically changeable via /proc/sys/*/overflowuid but nobody ever does)
-skipnot id nobody >/dev/null
-testing "pass user" "tar -c --owner nobody:65534 --group root --mtime @0 file | LST" \
-  "-rw-rw-r-- nobody/root 0 1970-01-01 00:00 file\n" "" ""
-# (We assume that if we have the nobody user, we also have the group, in the
-# absence of a good portable way to test for the existence of a named group.)
-skipnot id nobody >/dev/null
-testing "pass group" "tar c --owner root --group nobody:65534 --mtime @0 file | LST" \
+# Two files from -T list
+touch file1 file2
+testing "-T newline" "$TAR -T input | LST" \
+  "-rw-rw-r-- root/sys 0 2009-02-13 23:31 file1\n-rw-rw-r-- root/sys 0 2009-02-13 23:31 file2\n" "file1\nfile2\n" ""
+testing "-T null" "$TAR --null -T input | LST" \
+  "-rw-rw-r-- root/sys 0 2009-02-13 23:31 file1\n-rw-rw-r-- root/sys 0 2009-02-13 23:31 file2\n" "file1\0file2\0" ""
+
+# User "root" is UID 0 and group "sys" is GID 3 (on Linux, BSD, and Mac),
+# inherited from Bell Labs Unix v7
+
+# Note: testing both "tar c" and "tar -c" here.
+testing "specify UID, fetch GID" "tar -c --owner nobody:65534 --group sys --mtime @0 file | LST" \
+  "-rw-rw-r-- nobody/sys 0 1970-01-01 00:00 file\n" "" ""
+testing "fetch UID, specify GID" "tar c --owner root --group nobody:65534 --mtime @0 file | LST" \
   "-rw-rw-r-- root/nobody 0 1970-01-01 00:00 file\n" "" ""
 
-# Historically we output a "base 256" format that _we_ could decode but that
-# GNU tar choked on, so check the exact bytes with SUM, not a LST round trip.
+# Large values switch from ascii numbers to a binary format.
 testing "huge values" "tar c --owner 9999999 --group 8888888 --mtime @0 file | SUM 3" \
   "396b07fd2f80eeb312462e3bfb7dc1325dc6bcfb\n" "" ""
 
+testcmd "longname" "tf $FILES/tar/long_path.tar" \
+  "$(printf 'long file name%86cTRAILING' ' ' | tr ' ' _)\n" "" ""
+
 touch -t 198701231234.56 file
 testing "pass mtime" \
-  "tar c --owner root --group root file | LST --full-time" \
-  "-rw-rw-r-- root/root 0 1987-01-23 12:34:56 file\n" "" ""
+  "tar c --owner root --group sys file | LST --full-time" \
+  "-rw-rw-r-- root/sys 0 1987-01-23 12:34:56 file\n" "" ""
 
 testing "adjust mode" \
-  "tar c --owner root --group root --mode a+x file | LST --full-time" \
-  "-rwxrwxr-x root/root 0 1987-01-23 12:34:56 file\n" "" ""
+  "tar c --owner root --group sys --mode a+x file | LST --full-time" \
+  "-rwxrwxr-x root/sys 0 1987-01-23 12:34:56 file\n" "" ""
 
 mkdir dir
-testing "create dir" "$TAR dir | SUM 3" \
-  "05739c423d7d4a7f12b3dbb7c94149acb2bb4f8d\n" "" ""
-
+testing "store dir" "$TAR dir | SUM 3" \
+  "85add1060cfe831ca0cdc945158efe6db485b81e\n" "" ""
 testing "pass dir" "$TAR dir | LST" \
-  "drwxrwxr-x root/root 0 2009-02-13 23:31 dir/\n" "" ""
+  "drwxrwxr-x root/sys 0 2009-02-13 23:31 dir/\n" "" ""
 
 # note: does _not_ include dir entry in archive, just file
 touch dir/file
-testing "create file in dir" "$TAR dir/file | SUM 3" \
-  "2d7b96c7025987215f5a41f10eaa84311160afdb\n" "" ""
+testing "store file in dir" "$TAR dir/file | SUM 3" \
+  "d9e7fb3884430d29e7eed0dc04a2593dd260df14\n" "" ""
 
-# Tests recursion without worrying about content order
-testing "create dir and dir/file" "$TAR dir | SUM 3" \
-  "0bcc8005a3e07eb63c9b735267aecc5b774795d7\n" "" ""
+# Test recursion with one file so filesystem sort order can't change result
+testing "store dir and dir/file" "$TAR dir | SUM 3" \
+  "a4e35f87e28c4565b60ba01dbe79e431914f8788\n" "" ""
 
 testing "pass dir/file" "$TAR dir | LST" \
-  "drwxrwxr-x root/root 0 2009-02-13 23:31 dir/\n-rw-rw-r-- root/root 0 2009-02-13 23:31 dir/file\n" "" ""
+  "drwxrwxr-x root/sys 0 2009-02-13 23:31 dir/\n-rw-rw-r-- root/sys 0 2009-02-13 23:31 dir/file\n" "" ""
 
 echo boing > dir/that
 testing "tar C" "$TAR -C dir that | SUM 3" \
-  "f0deff71bf4858eb0c5f49d99d052f12f1831feb\n" "" ""
+  "d469d4bc06def2d8808400ba30025ca295d05e4f\n" "" ""
 
-# / and .. only stripped from name, not symlink target.
-ln -s ../name.././.. dir/link
-testing "create symlink" "$TAR dir/link | SUM 3" \
-  "7324cafbd9aeec5036b6efc54d741f11528aeb10\n" "" ""
-
-# Also two explicit targets
 ln dir/file dir/hardlink
-testing "create hardlink" "$TAR dir/file dir/hardlink | SUM 3" \
-  "c5383651f8c03ec0fe15e8a9e28a4e8e5273990d\n" "" ""
-
-ln dir/link dir/hlink
-testing "create hardlink to symlink" "$TAR dir/link dir/hlink | SUM 3" \
-  "3bc16f8fb6fc8b05f691da8caf989a70ee99284a\n" "" ""
+testing "store hardlink" "$TAR dir/file dir/hardlink | SUM 3" \
+  "519de8abd1b32debd495a0fc1d96082184abbdcc\n" "" ""
 
 skipnot mkfifo dir/fifo 2>/dev/null
 testing "create dir/fifo" "$TAR dir/fifo | SUM 3" \
-  "bd1365db6e8ead4c813333f9666994c1899924d9\n" "" ""
+  "cad477bd0fc5173d0a43f4774f514035456960e6\n" "" ""
 
 # test L and K records
 
 # 4+96=100 (biggest short name), 4+97=101 (shortest long name)
 touch dir/${LONG:1:96} dir/${LONG:1:97}
 testing "create long fname" "$TAR dir/${LONG:1:97} dir/${LONG:1:96} | SUM 3" \
-  "99348686fe9c9bf80f5740f1fc0c6f32f2021e3d\n" "" ""
+  "d70018505fa5df19ae73498cfc74d0281601e42e\n" "" ""
 
-ln -s dir/${LONG:1:96} dir/lshort
-ln -s dir/${LONG:1:97} dir/llong
-testing "create long symlnk" "$TAR dir/lshort dir/llong | SUM 3" \
-  "8a5d652dc85f252a2e3b3f47d1ecd699e98a5f4b\n" "" ""
+# MacOS X has different symlink permissions, skip these tests there
+[ "$(uname)" == Darwin ] && SKIP=999
 
-ln -s $LONG dir/${LONG:5}
-testing "create long->long" "$TAR dir/${LONG:5} | SUM 7" \
-  "543116b8e690a116a559ab5b673f9b6d6601c925\n" "" ""
-# absolute and relative link names, broken and not
+  # / and .. only stripped from name, not symlink target.
+  ln -s ../name.././.. dir/link
+  testing "create symlink" "$TAR dir/link | SUM 3" \
+    "f841bf9d757c655c5d37f30be62acb7ae24f433c\n" "" ""
 
-ln -s file dir/linkok
-testing "create symlink" "$TAR dir/linkok | SUM 3" \
-  "55652846506cf0a9d43b3ef03ccf9e98123befaf\n" "" ""
+  ln dir/link dir/hlink
+  testing "create hardlink to symlink" "$TAR dir/link dir/hlink | SUM 3" \
+    "de571a6dbf09e1485e513ad13a178b1729267452\n" "" ""
+
+  ln -s dir/${LONG:1:96} dir/lshort
+  ln -s dir/${LONG:1:97} dir/llong
+  testing "create long symlink" "$TAR dir/lshort dir/llong | SUM 3" \
+    "07eaf397634b5443dbf2d3ec38a4302150fcfe82\n" "" ""
+
+  ln -s $LONG dir/${LONG:5}
+  testing "create long->long" "$TAR dir/${LONG:5} | SUM 7" \
+    "b9e24f53e27496c5125445230d201b4a36ff7398\n" "" ""
+
+  # absolute and relative link names, broken and not
+  ln -s file dir/linkok
+  testing "create symlink" "$TAR dir/linkok | SUM 3" \
+    "f5669cfd179ddcdd5ca9f8a1561a99e11e0a08b1\n" "" ""
+
+SKIP=0 # End of tests that don't match MacOS symlink permissions
+
+symlink_perms=lrwxrwxrwx
+[ "$(uname)" == "Darwin" ] && symlink_perms=lrwxrwxr-x
 
 ln -s /dev/null dir/linknull
 testing "pass absolute symlink" "$TAR dir/linknull | LST" \
-  "lrwxrwxrwx root/root 0 2009-02-13 23:31 dir/linknull -> /dev/null\n" "" ""
+  "$symlink_perms root/sys 0 2009-02-13 23:31 dir/linknull -> /dev/null\n" "" ""
 
 ln -s rel/broken dir/relbrok
 testing "pass broken symlink" "$TAR dir/relbrok | LST" \
-  "lrwxrwxrwx root/root 0 2009-02-13 23:31 dir/relbrok -> rel/broken\n" "" ""
+  "$symlink_perms root/sys 0 2009-02-13 23:31 dir/relbrok -> rel/broken\n" "" ""
 
 ln -s /does/not/exist dir/linkabsbrok
 testing "pass broken absolute symlink" "$TAR dir/linkabsbrok | LST" \
-  "lrwxrwxrwx root/root 0 2009-02-13 23:31 dir/linkabsbrok -> /does/not/exist\n" \
+  "$symlink_perms root/sys 0 2009-02-13 23:31 dir/linkabsbrok -> /does/not/exist\n" \
   "" ""
 
-# this expects devtmpfs values
+nulldev=1,3 # devtmpfs values
+[ "$(uname)" == "Darwin" ] && nulldev=3,2
 
 testing "pass /dev/null" \
-  "tar c --mtime @0 /dev/null 2>/dev/null | LST" \
-  "crw-rw-rw- root/root 1,3 1970-01-01 00:00 dev/null\n" "" ""
+  "tar c --mtime @0 --group sys /dev/null 2>/dev/null | LST" \
+  "crw-rw-rw- root/sys $nulldev 1970-01-01 00:00 dev/null\n" "" ""
 testing "--absolute-names" \
-  "tar c --mtime @0 --absolute-names /dev/null 2>/dev/null | LST" \
-  "crw-rw-rw- root/root 1,3 1970-01-01 00:00 /dev/null\n" "" ""
+  "tar c --mtime @0 --group sys --absolute-names /dev/null 2>/dev/null | LST" \
+  "crw-rw-rw- root/sys $nulldev 1970-01-01 00:00 /dev/null\n" "" ""
 
 # compression types
 testing "autodetect gzip" 'LST -f "$FILES"/tar/tar.tgz' \
@@ -163,22 +176,24 @@
   "drwxr-x--- enh/eng 0 2017-05-13 01:05 dir/\n-rw-r----- enh/eng 12 2017-05-13 01:05 dir/file\n" \
   "" ""
 
-skipnot mknod dir/char c 12 34 2>/dev/null
-testing "character special" "tar --mtime @0 -cf test.tar dir/char && rm -f dir/char && tar xf test.tar && ls -l dir/char" \
-  "crw-rw---- 1 root root 12,  34 1970-01-01 00:00 dir/char\n" "" ""
+skipnot mknod -m 660 dir/char c 12 34 2>/dev/null && chgrp sys dir/char
+NOSPACE=1 testing "character special" "tar --mtime @0 -cf test.tar dir/char && rm -f dir/char && tar xf test.tar && ls -l --full-time dir/char" \
+  "crw-rw---- 1 root sys 12, 34 1970-01-01 00:00:00.000000000 +0000 dir/char\n"\
+  "" ""
 
-skipnot mknod dir/block b 23 45 2>/dev/null
-testing "block special" "tar --mtime @0 -cf test.tar dir/block && rm -f dir/block && tar xf test.tar && ls -l dir/block" \
-  "brw-rw---- 1 root root 23,  45 1970-01-01 00:00 dir/block\n" "" ""
+skipnot mknod -m 660 dir/block b 23 45 2>/dev/null && chgrp sys dir/block
+NOSPACE=1 testing "block special" "tar --mtime @0 -cf test.tar dir/block && rm -f dir/block && tar xf test.tar && ls -l --full-time dir/block" \
+  "brw-rw---- 1 root sys 23, 45 1970-01-01 00:00:00.000000000 +0000 dir/block\n"\
+  "" ""
 
-skipnot chown nobody dir/file 2>/dev/null
+skipnot chown nobody:nogroup dir/file 2>/dev/null
 testing "ownership" "$TAR dir/file | SUM 3" \
   "2d7b96c7025987215f5a41f10eaa84311160afdb\n" "" ""
 
 mkdir -p dd/sub/blah &&
 tar cf test.tar dd/sub/blah &&
 rm -rf dd/sub &&
-ln -s ../.. dd/sub || SKIPNEXT=1
+skipnot ln -s ../.. dd/sub
 toyonly testing "symlink out of cwd" \
   "tar xf test.tar 2> /dev/null || echo yes ; [ ! -e dd/sub/blah ] && echo yes" \
   "yes\nyes\n" "" ""
@@ -210,48 +225,59 @@
   "dir/\ndir/file\ndrwxr-x--- 1494637555 dd/dir\n-rw-r----- 1494637555 dd/dir/file\n" \
   "" ""
 
-yes | head -n $((1<<18)) > bang
-{ dd bs=$((1<<16)) count=1 status=none; dd bs=8192 seek=14 count=1 status=none; dd bs=4096 seek=64 count=5 status=none; } < bang > fweep
-testing "sparse without overflow" "$TAR --sparse fweep | SUM 3" \
-  "e1560110293247934493626d564c8f03c357cec5\n" "" ""
-rm bang fweep
+mkdir path && ln -s "$(which gzip)" "$(which tar)" path/ && [ -x path/gzip ] ||
+  ((++SKIP))
+toyonly testing "autodetect falls back to gzip -d when no zcat" \
+  "PATH=path; tar tf $FILES/tar/tar.tgz" "dir/\ndir/file\n" "" ""
+rm -rf path
 
-for i in 1 3 5 7 9 14 27 36 128 256 300 304
-do
-  dd if=/dev/zero of=fweep bs=65536 seek=$i count=1 2>/dev/null
-done
+# Tests that don't produce the same results on MacOS X as Linux
+[ "$(uname)" == Darwin ] && SKIP=999
 
-testing "sparse single overflow" "$TAR --sparse fweep | SUM 6" \
-  "063fc6519ea2607763bc591cc90dd15ac2b43eb8\n" "" ""
+  yes | head -n $((1<<18)) > bang
+  {
+    dd bs=$((1<<16)) count=1 status=none
+    dd bs=8192 seek=14 count=1 status=none
+    dd bs=4096 seek=64 count=5 status=none
+  } < bang > fweep
+  testing "sparse without overflow" "$TAR --sparse fweep | SUM 3" \
+    "50dc56c3c7eed163f0f37c0cfc2562852a612ad0\n" "" ""
+  rm bang fweep
 
-rm fweep
-for i in $(seq 8 3 200)
-do
-  dd if=/dev/zero of=fweep bs=65536 seek=$i count=1 2>/dev/null
-  dd if=/dev/zero of=fweep2 bs=65536 seek=$i count=1 2>/dev/null
-done
-truncate -s 20m fweep2
+  for i in 1 3 5 7 9 14 27 36 128 256 300 304
+  do
+    dd if=/dev/zero of=fweep bs=65536 seek=$i count=1 2>/dev/null
+  done
+  testing "sparse single overflow" "$TAR --sparse fweep | SUM 6" \
+    "81d59c3a7470201f92d60e63a43318ddde893f6d\n" "" ""
+  rm fweep
 
-testing "sparse double overflow" "$TAR --sparse fweep | SUM 7" \
-  "f1fe57f8313a9d682ec9013a80f3798910b6ff51\n" "" ""
+  for i in $(seq 8 3 200)
+  do
+    dd if=/dev/zero of=fweep bs=65536 seek=$i count=1 2>/dev/null
+    dd if=/dev/zero of=fweep2 bs=65536 seek=$i count=1 2>/dev/null
+  done
+  truncate -s 20m fweep2
+  testing "sparse double overflow" "$TAR --sparse fweep | SUM 7" \
+    "024aacd955e45f89bafedb3f37c8d39b4d556471\n" "" ""
 
-tar c --sparse fweep > fweep.tar
-rm fweep
-testing "sparse extract" "tar xf fweep.tar && $TAR --sparse fweep | SUM 4" \
-  "38dc57b8b95632a287db843c214b5c96d1cfe415\n" "" ""
-testing "sparse tvf" "tar tvf fweep.tar | grep -wq 13172736 && echo right size"\
-  "right size\n" "" ""
-rm fweep fweep.tar
+  tar c --sparse fweep > fweep.tar
+  rm fweep
+  testing "sparse extract" "tar xf fweep.tar && $TAR --sparse fweep | SUM 4" \
+    "b949d3a3b4c6457c873f1ea9918fd9029c5ed4b3\n" "" ""
+  testing "sparse tvf" \
+    "tar tvf fweep.tar | grep -wq 13172736 && echo right size" "right size\n" \
+    "" ""
+  rm fweep fweep.tar
 
-tar c --sparse fweep2 > fweep2.tar
-rm fweep2
-testing "sparse extract hole at end" \
-  "tar xf fweep2.tar && $TAR --sparse fweep2 | SUM 4" \
-  "791060574c569e5c059e2b90c1961a3575898f97\n" "" ""
-rm fweep2 fweep2.tar
+  tar c --sparse fweep2 > fweep2.tar
+  rm fweep2
+  testing "sparse extract hole at end" \
+    "tar xf fweep2.tar && $TAR --sparse fweep2 | SUM 4" \
+    "807664bcad0e827793318ff742991d6f006b2127\n" "" ""
+  rm fweep2 fweep2.tar
 
-testcmd "longname" "tf $FILES/tar/long_path.tar" \
-  "$(printf 'long file name%86cTRAILING' ' ' | tr ' ' _)\n" "" ""
+SKIP=0 # End of tests that don't work on MacOS X
 
 mkdir -p links
 touch links/orig
@@ -278,14 +304,125 @@
 
 mkdir ..dotsdir
 testing "create ..dotsdir" "$TAR ..dotsdir | SUM 3" \
-  "de99091a91c74ef6b90093e9165b413670730572\n" "" ""
+  "62ff23c9b427020331992b9bc71f082099c1411f\n" "" ""
 
 testing "pass ..dotsdir" "$TAR ..dotsdir | LST" \
-  "drwxrwxr-x root/root 0 2009-02-13 23:31 ..dotsdir/\n" "" ""
+  "drwxrwxr-x root/sys 0 2009-02-13 23:31 ..dotsdir/\n" "" ""
 rmdir ..dotsdir
 
+mkdir -p one/two/three/four/five
+touch one/two/three/four/five/six
+testing "--strip" "$TAR one | tar t --strip=2 --show-transformed | grep six" \
+  "three/four/five/six\n" "" ""
+
+# toybox tar --xform depends on toybox sed
+[ -z "$TEST_HOST" ] && ! sed --tarxform '' </dev/null 2>/dev/null && SKIP=99
+
+mkdir uno
+ln -s tres uno/dos
+touch uno/tres
+ln uno/tres uno/quatro
+LL() { LST --show-transformed-names $XX | sed 's/^.* 23:31 //'; }
+TT() { $TAR --no-recursion uno uno/{dos,tres,quatro} "$@" | LL; }
+testing 'xform S' \
+  "TT --xform 's/uno/one/S;s/dos/two/S;s/tres/three/S;s/quatro/four/S'" \
+  "one/\none/two -> tres\none/three\none/four link to one/three\n" "" ""
+
+testing 'xform flags=rh starts with all disabled' \
+  "TT --xform 's/uno/one/;flags=rh;s/dos/two/;s/tres/three/;s/quatro/four/'" \
+  "one/\none/two -> tres\none/three\none/four link to one/three\n" "" ""
+
+testing 'xform flags=rHhsS toggles' \
+  "TT --xform 's/uno/one/;flags=rHhsS;s/dos/two/;s/tres/three/;s/quatro/four/'"\
+  "one/\none/two -> tres\none/three\none/four link to one/three\n" "" ""
+
+testing 'xform flags= is not a delta from previous' \
+  "TT --xform 'flags=s;flags=rh;s/uno/one/;s/dos/two/;s/tres/three/;s/quatro/four/'" \
+  "one/\none/two -> tres\none/three\none/four link to one/three\n" "" ""
+
+testing 'xform H' \
+  "TT --xform 'flags=rsH;s/uno/one/;s/dos/two/;s/tres/three/;s/quatro/four/'" \
+  "one/\none/two -> three\none/three\none/four link to uno/tres\n" "" ""
+
+testing 'xform R' \
+  "TT --xform 'flags=rshR;s/uno/one/;s/dos/two/;s/tres/three/;s/quatro/four/'" \
+  "uno/\nuno/dos -> three\nuno/tres\nuno/quatro link to one/three\n" "" ""
+
+testing "xform path" "$TAR one --xform=s@three/four/@zero@ | tar t | grep six" \
+  "one/two/zerofive/six\n" "" ""
+
+testing "xform trailing slash special case" \
+  "$TAR --xform 's#^.+/##x' one/two/three/four/five | tar t" 'five/\nsix\n' '' ''
+
+# The quoting works because default IFS splits on whitepace not ;
+testing "xform extract all" \
+  "XX='--xform s/uno/one/;s/dos/two/;s/tres/three/;s/quatro/four/' TT" \
+  'one/\none/two -> three\none/three\none/four link to one/three\n' '' ''
+
+testing 'xform extract S' \
+  "XX='--xform s/uno/one/S;s/dos/two/S;s/tres/three/S;s/quatro/four/S' TT" \
+  "one/\none/two -> tres\none/three\none/four link to one/three\n" "" ""
+
+testing 'xform extract H' \
+  "XX='--xform flags=rs;s/uno/one/;s/dos/two/;s/tres/three/;s/quatro/four/' TT"\
+  "one/\none/two -> three\none/three\none/four link to uno/tres\n" "" ""
+
+testing 'xform extract R' \
+  "XX='--xform flags=sh;s/uno/one/;s/dos/two/;s/tres/three/;s/quatro/four/' TT"\
+  "uno/\nuno/dos -> three\nuno/tres\nuno/quatro link to one/three\n" "" ""
+
+rm -rf uno
+SKIP=0
+rm -rf one
+
+testing '-P' "$TAR -P --no-recursion -C / /// .. | SUM 3" \
+  "a3e94211582da121845d823374d8f41ead62d7bd\n" "" ""
+
+testing 'without -P' "$TAR --no-recursion -C / /// .. 2>/dev/null | SUM 3" \
+  "077d03243e247b074806904885e6da272fd5857a\n" "" ""
+
+# Wildcards: --exclude, include (create/extract * cmdline/recursive)
+# --anchored, --wildcards, --wildcards-match-slash
+# --no-* versions of each. Span coverage, switching on/off...
+
+#pattern a.c
+#  abcd dabc a/c da/c
+#  top/*
+
+mkdir sub && cd sub && mkdir -p a da top/a top/da &&
+touch abcd dabc a/c da/c top/abcd top/dabc top/a/c top/da/c &&
+$TAR -f ../sub.tar abcd dabc a da top && cd .. || exit 1
+
+# TODO I have not made wildcard state changes positional.
+
+testing 'wildcards do not affect creation cmdline args' \
+  '$TAR -C sub --wildcards a.cd abcd dabc a da top 2>/dev/null | cmp - sub.tar' \
+  '' '' ''
+
+testing 'creation --exclude --no-wildcards'\
+  '$TAR -C sub --no-wildcards --exclude=d?bc abcd dabc | LL' \
+  'abcd\ndabc\n' '' ''
+
+
+testing 'creation --wildcards --exclude'\
+  '$TAR -C sub --wildcards --exclude=d?bc abcd dabc | LL' \
+  'abcd\n' '' ''
+
+# TODO: do we need to set DIRTREE_BREADTH at top level? Come up with test if so.
+mkdir sub2
+touch sub2/{ephebe,klatch,djelibeybi}
+testing 'tsort' '$TAR -c sub2 --sort=name | tar t' \
+  'sub2/\nsub2/djelibeybi\nsub2/ephebe\nsub2/klatch\n' '' ''
+
+touch file
+testing './file bug' 'tar c ./file > tar.tar && tar t ./file < tar.tar' \
+  './file\n' '' ''
+
 if false
 then
+# Sequencing issues that leak implementation details out the interface
+testing "what order are --xform, --strip, and --exclude processed in?"
+testing "--xform vs ../ removal and adding / to dirs"
 
 chmod 700 dir
 tar cpf tar.tgz dir/file
@@ -322,8 +459,4 @@
 
 fi
 
-TZ="$OLDTZ"
-umask $OLDUMASK
-unset LONG TAR SUM OLDUMASK OLDTZ
-unset -f LST
-rm save.dat
+rm -f save.dat
diff --git a/tests/test.test b/tests/test.test
index 1295be4..2174f40 100644
--- a/tests/test.test
+++ b/tests/test.test
@@ -4,14 +4,23 @@
 
 #testing "name" "command" "result" "infile" "stdin"
 
-testcmd '0 args' '; echo $?'  '1\n' '' ''
-testcmd '1 arg' '== ; echo $?' '0\n' '' ''
+testcmd "-- isn't parsed" "-- == -- && echo yes" "yes\n" "" ""
+
+# Number and position of args is important
+testcmd 'no args is false' '; echo $?'  '1\n' '' ''
+testcmd 'empty string is false' '""; echo $?' '1\n' '' ''
+testcmd '1 arg is true if not empty string' '== ; echo $?' '0\n' '' ''
+testcmd "1 arg isn't an operand" '-t 2>&1; echo $?' '0\n' '' ''
 testcmd '2 args' '-e == ; echo $?' '1\n' '' ''
 testcmd '3 args' '-e == -e ; echo $?' '0\n' '' ''
+
+# parse as operator before parsing as parentheses around one argument
 testcmd '' '\( == \) ; echo $?' '1\n' '' ''
 testcmd '' '\( == \( ; echo $?' '0\n' '' ''
+testcmd '' '\( "" \) ; echo $?' '1\n' '' ''
+testcmd '' '\( x \) ; echo $?' '0\n' '' ''
 
-# TODO: Should also have device and socket files
+# TODO: Should also have device and socket files, but requires root
 
 mkdir d
 touch f
@@ -30,28 +39,34 @@
 testing "-b" "type_test -b" "" "" ""
 testing "-c" "type_test -c" "L" "" ""
 testing "-d" "type_test -d" "d" "" ""
+testing "-e" "type_test -e" "dfLsp" "" ""
 testing "-f" "type_test -f" "fs" "" ""
 testing "-h" "type_test -h" "L" "" ""
 testing "-L" "type_test -L" "L" "" ""
-testing "-s" "type_test -s" "ds" "" ""
-testing "-S" "type_test -S" "" "" ""
 testing "-p" "type_test -p" "p" "" ""
-testing "-e" "type_test -e" "dfLsp" "" ""
+testing "-S" "type_test -S" "" "" ""
+testing "-s" "type_test -s" "ds" "" ""
 testing "! -e" 'type_test ! -e' "n" "" ""
 
 rm f L s p
 rmdir d
 
+# Alas can't expand to a redirect, so just test one success/fail
+testcmd "-t" '-t 0 < /dev/null; echo $?' '1\n' '' ''
+testcmd "-t2" '-t 0 < /dev/ptmx; echo $?' '0\n' '' ''
+
 # test -rwx each bit position and failure
 touch walrus
 MASK=111
 for i in x w r k g u; do
   [ $i == k ] && MASK=1000
+  XX=no
+  [ $(id -u) -eq 0 ] && [ $i == r -o $i == w ] && XX=yes  # Root always has access
   # test everything off produces "off"
   chmod 000 walrus
-  testcmd "-$i 0" "-$i walrus || echo yes" "yes\n" "" ""
+  testcmd "-$i 0" "-$i walrus && echo yes || echo no" "$XX\n" "" ""
   chmod $((7777-$MASK)) walrus
-  testcmd "-$i inverted" "-$i walrus || echo yes" "yes\n" "" ""
+  testcmd "-$i inverted" "-$i walrus && echo yes || echo no" "$XX\n" "" ""
   MASK=$(($MASK<<1))
 done
 unset MASK
@@ -62,15 +77,19 @@
   testcmd "-${i:0:1}" "-${i:0:1} walrus && echo yes" "yes\n" "" ""
 done
 # test each ugo+rwx bit position individually
+XX=no
+# Note: chmod 007 means everybody EXCEPT owner/group can access it. (Unix!)
+[ $(id -u) -eq 0 ] && XX=yes  # Root always has access
 for i in 1 10 100; do for j in x w r; do
   chmod $i walrus
-  testcmd "-$j $i" "-$j walrus && echo yes" "yes\n" "" ""
+
+  [ $i == 100 ] && XX=yes
+  testcmd "-$j $i" "-$j walrus && echo yes || echo no" "$XX\n" "" ""
   i=$((i<<1))
 done; done
 rm -f walrus
 
-testcmd "" "'' || echo yes" "yes\n" "" ""
-testcmd "" "a && echo yes" "yes\n" "" ""
+# Not zero length, zero length, equals, not equals
 testcmd "-n" "-n '' || echo yes" "yes\n" "" ""
 testcmd "-n2" "-n a && echo yes" "yes\n" "" ""
 testcmd "-z" "-z '' && echo yes" "yes\n" "" ""
@@ -94,12 +113,24 @@
 testing "-lt" "arith_test -lt" "l" "" ""
 testing "-le" "arith_test -le" "le" "" ""
 
+testing "positional" "test -a == -a && echo yes" "yes\n" "" ""
+testing "! stacks" 'test \! \! \! \! 2 -eq 2 && echo yes' "yes\n" "" ""
+
+# bash builtin "test" has these, but /usr/bin/test does not.
+testing "<1" 'test abc \< def && echo yes' "yes\n" "" ""
+testing "<2" 'test def \< abc || echo yes' "yes\n" "" ""
+testing ">1" 'test abc \> def || echo yes' "yes\n" "" ""
+testing ">2" 'test def \> abc && echo yes' "yes\n" "" ""
+# bash only has this for [[ ]] but extra tests to _exclude_ silly...
+toyonly testcmd "=~" 'abc =~ a.c && echo yes' "yes\n" "" ""
+toyonly testcmd "=~ fail" 'abc =~ d.c; echo $?' '1\n' "" ""
+toyonly testcmd "=~ zero length match" 'abc =~ "1*" && echo yes' 'yes\n' '' ''
+
 # test ! = -o a
 # test ! \( = -o a \)
 # test \( ! = \) -o a
 # test \( \)
 
-#testing "" "[ -a -eq -a ] && echo yes" "yes\n" "" ""
 
 # -e == -a
 # -e == -a -o -d != -o
@@ -111,3 +142,12 @@
 #  // x -o ( x -a x ) -a x -o x
 
 # trailing ! and (
+# test \( ! ! ! -e \) \)
+# test \( \( "" \) -a "" \) -a ""
+# test !
+# test \( \) == \) \) -a x
+
+# test \( "" \) -a \) == \)
+# test \( "x" \) -a \) == \)
+# test -e == -a
+# test \( "" \)
diff --git a/tests/timeout.test b/tests/timeout.test
old mode 100644
new mode 100755
index 18f9379..694540a
--- a/tests/timeout.test
+++ b/tests/timeout.test
@@ -23,7 +23,7 @@
 # signal and exits, we need to report that as a timeout (unless overridden).
 cat > loop.sh <<EOF
 #!/bin/sh
-trap "exit 3" SIGTERM
+trap "exit 3" TERM
 while true; do
   :
 done
@@ -33,3 +33,10 @@
 testcmd "trap-and-exit --preserve-status" \
   '--preserve-status 1 ./loop.sh ; echo $?' '3\n' '' ''
 rm loop.sh
+
+toyonly testcmd "-i" \
+  "-i 1 sh -c 'for i in .25 .50 2; do sleep \$i; echo hello; done'" \
+  "hello\nhello\n" "" ""
+testing '-v' "{ timeout -v .1 sleep 3;} 2>&1 | egrep -o 'TERM|sleep'" \
+  'TERM\nsleep\n' '' ''
+
diff --git a/tests/truncate.test b/tests/truncate.test
index 253af62..2bb0828 100755
--- a/tests/truncate.test
+++ b/tests/truncate.test
@@ -9,7 +9,10 @@
 testing "12345" "truncate -s 12345 freep $SIZE" "12345\n" "" ""
 testing "1m" "truncate -s 1m freep $SIZE" "1048576\n" "" ""
 # We can't test against 0 because Android filesystems use an extra 4KiB for
-# extended attributes (SELinux).
+# extended attributes (SELinux). We recreate the file because macOS behavior
+# is a bit weird; for some file sizes (12345, in this example) blocks will
+# have been allocated that aren't deallocated by the 1g extension.
+rm freep; touch freep
 testing "is sparse" "truncate -s 1g freep && [ $(stat -c %b freep) -le 8 ] &&
   echo okay" \
 	"okay\n" "" ""
diff --git a/tests/xargs.test b/tests/xargs.test
index dc3c7b3..7566e37 100644
--- a/tests/xargs.test
+++ b/tests/xargs.test
@@ -84,3 +84,5 @@
 #testing "-n exact match"
 #testing "-s exact match"
 #testing "-s impossible"
+
+testing "no stdin" "echo -n | xargs cat" "" "" ""
diff --git a/tests/xxd.test b/tests/xxd.test
index e9ec81e..3b350a4 100755
--- a/tests/xxd.test
+++ b/tests/xxd.test
@@ -9,45 +9,63 @@
 
 # Note that the xxd in vim-common on Ubuntu 14 uses %07x for the file offset.
 
-testing "file1" "xxd file1" \
+testcmd "file1" "file1" \
     "00000000: 7468 6973 2069 7320 736f 6d65 2074 6578  this is some tex\n00000010: 740a                                     t.\n" \
     "" ""
-testing "file1 -l" "xxd -l 2 file1" \
+testcmd "file1 -l" "-l 2 file1" \
     "00000000: 7468                                     th\n" \
     "" ""
-testing "-" "xxd -" \
+testcmd "-" "-" \
     "00000000: 6865 6c6c 6f                             hello\n" "" "hello"
-testing "xxd" "xxd" \
+testcmd "no args" "" \
     "00000000: 776f 726c 64                             world\n" "" "world"
-testing "-c 8 -g 4 file1" "xxd -c 8 -g 4 file1" \
+testcmd "-c 8 -g 4 file1" "-c 8 -g 4 file1" \
     "00000000: 74686973 20697320  this is \n00000008: 736f6d65 20746578  some tex\n00000010: 740a               t.\n" "" ""
-testing "-c 8 -g 3 file1" "xxd -c 8 -g 3 file1" \
-    "00000000: 746869 732069 7320 this is \n00000008: 736f6d 652074 6578 some tex\n00000010: 740a               t.\n" "" ""
+testcmd "-c 8 -g 3 file1" "-c 8 -g 3 file1" \
+    "00000000: 746869 732069 7320  this is \n00000008: 736f6d 652074 6578  some tex\n00000010: 740a                t.\n" "" ""
 
-testing "-i" "cat file1 | xxd -i -" "  0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6d, 0x65,\n  0x20, 0x74, 0x65, 0x78, 0x74, 0x0a\n" "" ""
+testcmd "-i" "-i - < file1" "  0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6d, 0x65,\n  0x20, 0x74, 0x65, 0x78, 0x74, 0x0a\n" "" ""
 
-testing "-o 0x8000" "xxd -o 0x8000 file1" "00008000: 7468 6973 2069 7320 736f 6d65 2074 6578  this is some tex\n00008010: 740a                                     t.\n" "" ""
+testcmd "-o 0x8000" "-o 0x8000 file1" "00008000: 7468 6973 2069 7320 736f 6d65 2074 6578  this is some tex\n00008010: 740a                                     t.\n" "" ""
 
-testing "-p" "xxd -p file1" "7468697320697320736f6d6520746578740a\n" "" ""
+testcmd "-p" "-p file1" "7468697320697320736f6d6520746578740a\n" "" ""
 
-testing "-s" "xxd -s 13 file1" "0000000d: 7465 7874 0a                             text.\n" "" ""
+# TODO: remove toyonly when distro catches up
+toyonly testcmd "-pc0" "-pc0" \
+  "73686f77203830206865782064696769747320776974686f757420776f72647772617070696e670a\n" \
+  "" "show 80 hex digits without wordwrapping\n"
+toyonly testcmd "-pc0 long" "-pc0 | wc -c" "97787\n" "" "$(seq 1 10000)"
 
-testing "-r" "echo -e '    00000000: 7468 6973 2069 7320 736f 6d65 2074 6578  this is some tex\n00000010: 740a                                     t.' | xxd -r" "this is some text\n" "" ""
-toyonly testing "-r -i" "echo -e '0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6d, 0x65,\n  0x20, 0x74, 0x65, 0x78, 0x74, 0x0a' | xxd -ri" "this is some text\n" "" ""
-testing "-r -p" "echo 7468697320697320736f6d6520746578740a | xxd -r -p" "this is some text\n" "" ""
+testcmd "-s" "-s 13 file1" \
+  "0000000d: 7465 7874 0a                             text.\n" "" ""
 
-testing "-r garbage" "echo '0000: 68 65 6c6c 6fxxxx' | xxd -r -" "hello" "" ""
+testcmd "-r" "-r" "this is some text\n" "" \
+  '    00000000: 7468 6973 2069 7320 736f 6d65 2074 6578  this is some tex\n00000010: 740a                                     t.\n'
+
+toyonly testcmd "-r -i" "-ri" "this is some text\n" "" \
+  '0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6d, 0x65,\n  0x20, 0x74, 0x65, 0x78, 0x74, 0x0a\n'
+
+testcmd "-r garbage" '-r -' 'hello' '' '0000: 68 65 6c6c 6fxxxx\n'
 
 # -r will only read -c bytes (default 16) before skipping to the next line,
 # ignoring the rest.
-testing "-r long" \
-    "echo '0000: 40404040404040404040404040404040404040404040404040404040404040404040404040404040' | xxd -r -" \
-    "@@@@@@@@@@@@@@@@" "" ""
+testcmd "-r long" '-r -' "@@@@@@@@@@@@@@@@" "" \
+    '0000: 40404040404040404040404040404040404040404040404040404040404040404040404040404040\r'
 
 # -r -p ignores the usual -p 30-byte/line limit (or any limit set by -c) and
 # will take as many bytes as you give it.
-testing "-r -p long" \
-    "echo '40404040404040404040404040404040404040404040404040404040404040404040404040404040' | xxd -r -p -" \
-    "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" "" ""
+testcmd "-r -p long" '-r -p -' "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" "" \
+    '40404040404040404040404040404040404040404040404040404040404040404040404040404040\n'
+
+testcmd "-r unnecessary output seeks" '-r | xxd' \
+  "00000000: 0100 0000 0000 0000 0000 0000 0000 00ff  ................\n" '' \
+  '00000000: 0100 0000 0000 0000 0000 0000 0000 00ff  deadbeef........\n'
+
+# Little-endian, testing both the "EOF in first word on line" and "EOF in word
+# mid-line" cases.
+testcmd "LE partial" "-e -" \
+    "00000000:     6568                             he\n" "" "he"
+testcmd "LE partial mid-line" "-e -" \
+    "00000000: 6c6c6568       6f                    hello\n" "" "hello"
 
 rm file1 file2
diff --git a/tests/zcat.test b/tests/zcat.test
index 57af109..878a11d 100755
--- a/tests/zcat.test
+++ b/tests/zcat.test
@@ -4,17 +4,17 @@
 
 #testing "name" "command" "result" "infile" "stdin"
 
-echo -n "foo " | gzip > f1.gz
-echo "bar" | gzip > f2.gz
+echo -n "hi " | gzip > 1.gz
+echo "there" | gzip > 2.gz
 
-# zcat is basically just `gzip -dc`...
-testing "files" "zcat f1.gz f2.gz && test -f f1.gz && test -f f2.gz" \
-    "foo bar\n" "" ""
-
-# zcat -c is allowed, but the -c changes nothing.
-testing "-c" "zcat -c f1.gz f2.gz && test -f f1.gz && test -f f2.gz" \
-    "foo bar\n" "" ""
+# zcat is basically just gzip -dc
+testcmd "files" "1.gz 2.gz && test -f 1.gz && test -f 2.gz" "hi there\n" "" ""
+# zcat -c is allowed but changes nothing
+testcmd "-c" "-c 1.gz 2.gz && test -f 1.gz && test -f 2.gz" "hi there\n" "" ""
+testing "concatenated" "{ cat 1.gz 2.gz; } | zcat" "hi there\n" "" ""
+testing "error" "head -c 10 2.gz | { zcat 2>/dev/null || echo fail; }" "fail\n"\
+  "" ""
 
 # TODO: how to test "zcat -f"?
 
-rm -f f1 f2 f1.gz f2.gz
+rm -f 1 2 1.gz 2.gz
diff --git a/toys.h b/toys.h
index 81c4955..ace3b26 100644
--- a/toys.h
+++ b/toys.h
@@ -82,6 +82,11 @@
 
 // These live in main.c
 
+#define HELP_USAGE   1  // usage: line only
+#define HELP_HEADER  2  // Add Toybox header line to help output
+#define HELP_SEE     4  // "See COMMAND" instead of dereferencing alias
+#define HELP_HTML    8  // Output HTML
+
 struct toy_list *toy_find(char *name);
 void show_help(FILE *out, int full);
 void check_help(char **arg);
@@ -124,7 +129,7 @@
 
 extern char **environ, *toybox_version, toybuf[4096], libbuf[4096];
 
-#define FLAG(x) (toys.optflags&FLAG_##x)
+#define FLAG(x) (!!(toys.optflags&FLAG_##x))  // Return 1 if flag set, 0 if not
 
 #define GLOBALS(...)
 #define ARRAY_LEN(array) (sizeof(array)/sizeof(*array))
@@ -134,5 +139,5 @@
 #ifndef TOYBOX_VENDOR
 #define TOYBOX_VENDOR ""
 #endif
-#define TOYBOX_VERSION "0.8.6"TOYBOX_VENDOR
+#define TOYBOX_VERSION "0.8.9"TOYBOX_VENDOR
 #endif
diff --git a/toys/android/log.c b/toys/android/log.c
index 0f7b387..005f714 100644
--- a/toys/android/log.c
+++ b/toys/android/log.c
@@ -23,18 +23,26 @@
 
 GLOBALS(
   char *t, *p;
+
+  int pri;
 )
 
+static void log_line(char **pline, long len)
+{
+  if (!pline) return;
+  __android_log_write(TT.pri, TT.t, *pline);
+}
+
 void log_main(void)
 {
-  android_LogPriority pri = ANDROID_LOG_INFO;
   char *s = toybuf;
   int i;
 
+  TT.pri = ANDROID_LOG_INFO;
   if (TT.p) {
     i = stridx("defisvw", tolower(*TT.p));
     if (i==-1 || strlen(TT.p)!=1) error_exit("bad -p '%s'", TT.p);
-    pri = (android_LogPriority []){ANDROID_LOG_DEBUG, ANDROID_LOG_ERROR,
+    TT.pri = (int[]) {ANDROID_LOG_DEBUG, ANDROID_LOG_ERROR,
       ANDROID_LOG_FATAL, ANDROID_LOG_INFO, ANDROID_LOG_SILENT,
       ANDROID_LOG_VERBOSE, ANDROID_LOG_WARN}[i];
   }
@@ -51,7 +59,7 @@
       }
       s = stpcpy(s, toys.optargs[i]);
     }
-  } else toybuf[readall(0, toybuf, 1024-1)] = 0;
+  } else do_lines(0, '\n', log_line);
 
-  __android_log_write(pri, TT.t, toybuf);
+  __android_log_write(TT.pri, TT.t, toybuf);
 }
diff --git a/toys/android/runcon.c b/toys/android/runcon.c
index 8831cbf..5eb8fa6 100644
--- a/toys/android/runcon.c
+++ b/toys/android/runcon.c
@@ -2,7 +2,7 @@
  *
  * Copyright 2015 The Android Open Source Project
 
-USE_RUNCON(NEWTOY(runcon, "<2", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_RUNCON(NEWTOY(runcon, "^<2", TOYFLAG_USR|TOYFLAG_SBIN))
 
 config RUNCON
   bool "runcon"
diff --git a/toys/example/skeleton.c b/toys/example/skeleton.c
index 5408068..4382e7d 100644
--- a/toys/example/skeleton.c
+++ b/toys/example/skeleton.c
@@ -12,7 +12,7 @@
 // Accept many different kinds of command line argument (see top of lib/args.c)
 // Demonstrate two commands in the same file (see www/documentation.html)
 
-USE_SKELETON(NEWTOY(skeleton, "(walrus)(blubber):;(also):e@d*c#b:a", TOYFLAG_USR|TOYFLAG_BIN))
+USE_SKELETON(NEWTOY(skeleton, "(walrus)(blubber):;(also):h(hlong):; g(glong): f(longf):;e@d*c#b:a", TOYFLAG_USR|TOYFLAG_BIN))
 USE_SKELETON_ALIAS(NEWTOY(skeleton_alias, "b#dq", TOYFLAG_USR|TOYFLAG_BIN))
 
 config SKELETON
@@ -51,7 +51,7 @@
       long c;
       struct arg_list *d;
       long e;
-      char *also, *blubber;
+      char *f, *g, *h, *also, *blubber;
     } s;
     struct {
       long b;
@@ -61,9 +61,6 @@
   int more_globals;
 )
 
-// Don't blindly build allyesconfig. The maximum _sane_ config is defconfig.
-#warning skeleton.c is just an example, not something to deploy.
-
 // Parse many different kinds of command line argument:
 void skeleton_main(void)
 {
@@ -82,6 +79,9 @@
     TT.s.d = TT.s.d->next;
   }
   if (TT.s.e) printf("e was seen %ld times\n", TT.s.e);
+  if (TT.s.f) printf("f=%s\n", TT.s.f);
+  if (TT.s.g) printf("g=%s\n", TT.s.g);
+  if (TT.s.h) printf("h=%s\n", TT.s.h);
   for (optargs = toys.optargs; *optargs; optargs++)
     printf("optarg=%s\n", *optargs);
   if (FLAG(walrus)) printf("Saw --walrus\n");
diff --git a/toys/lsb/dmesg.c b/toys/lsb/dmesg.c
index 384d6fc..5ce590c 100644
--- a/toys/lsb/dmesg.c
+++ b/toys/lsb/dmesg.c
@@ -4,10 +4,9 @@
  *
  * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/dmesg.html
  *
- * Don't ask me why the horrible new dmesg API is still in "testing":
+ * Linux 6.0 celebrates the 10th anniversary of this being in "testing":
  * http://kernel.org/doc/Documentation/ABI/testing/dev-kmsg
 
-// We care that FLAG_c is 1, so keep c at the end.
 USE_DMESG(NEWTOY(dmesg, "w(follow)CSTtrs#<1n#c[!Ttr][!Cc][!Sw]", TOYFLAG_BIN))
 
 config DMESG
@@ -48,7 +47,7 @@
 static void format_message(char *msg, int new)
 {
   unsigned long long time_s, time_us;
-  int facpri, subsystem, pos;
+  int facpri, subsystem, pos, ii, jj, in, out;
   char *p, *text;
 
   // The new /dev/kmsg and the old syslog(2) formats differ slightly.
@@ -72,6 +71,12 @@
   if (FLAG(r)) {
     color(0);
     printf("<%d>", facpri);
+  } else for (in = out = subsystem;; ) {
+    jj = 0;
+    if (text[in]=='\\'&& 1==sscanf(text+in, "\\x%2x%n", &ii, &jj) && jj==4) {
+      in += 4;
+      text[out++] = ii;
+    } else if (!(text[out++] = text[in++])) break;
   }
 
   // Format the time.
@@ -131,7 +136,7 @@
 
     // Each read returns one message. By default, we block when there are no
     // more messages (--follow); O_NONBLOCK is needed for for usual behavior.
-    fd = open("/dev/kmsg", O_RDONLY|(O_NONBLOCK*!FLAG(w)));
+    fd = open("/dev/kmsg", O_RDONLY|O_NONBLOCK*!FLAG(w));
     if (fd == -1) goto klogctl_mode;
 
     // SYSLOG_ACTION_CLEAR(5) doesn't actually remove anything from /dev/kmsg,
diff --git a/toys/lsb/gzip.c b/toys/lsb/gzip.c
index 049285a..b80e24f 100644
--- a/toys/lsb/gzip.c
+++ b/toys/lsb/gzip.c
@@ -5,18 +5,18 @@
  * See http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/gzip.html
  * GZIP RFC: http://www.ietf.org/rfc/rfc1952.txt
  *
- * todo: qtv --rsyncable
+ * TODO: qv --rsyncable
 
 // gzip.net version allows all options for all commands.
-USE_GZIP(NEWTOY(gzip,    "ncdfk123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_GUNZIP(NEWTOY(gunzip, "cdfk123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_ZCAT(NEWTOY(zcat,     "cdfk123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_GZIP(NEWTOY(gzip,    "n(no-name)cdfkt123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_GUNZIP(NEWTOY(gunzip, "cdfkt123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_ZCAT(NEWTOY(zcat,     "cdfkt123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
 
 config GZIP
   bool "gzip"
   default n
   help
-    usage: gzip [-19cdfk] [FILE...]
+    usage: gzip [-19cdfkt] [FILE...]
 
     Compress files. With no files, compresses stdin to stdout.
     On success, the input files are removed and replaced by new
@@ -26,13 +26,14 @@
     -d	Decompress (act as gunzip)
     -f	Force: allow overwrite of output file
     -k	Keep input files (default is to remove)
+    -t	Test integrity
     -#	Compression level 1-9 (1:fastest, 6:default, 9:best)
 
 config GUNZIP
   bool "gunzip"
   default y
   help
-    usage: gunzip [-cfk] [FILE...]
+    usage: gunzip [-cfkt] [FILE...]
 
     Decompress files. With no files, decompresses stdin to stdout.
     On success, the input files are removed and replaced by new
@@ -41,6 +42,7 @@
     -c	Output to stdout (act as zcat)
     -f	Force: allow read from tty
     -k	Keep input files (default is to remove)
+    -t	Test integrity
 
 config ZCAT
   bool "zcat"
@@ -116,7 +118,7 @@
 {
   struct stat sb;
   char *out = 0;
-  int ofd = 0;
+  int ofd = FLAG(t) ? xopen("/dev/null", O_WRONLY) :  0;
 
   // Are we writing to stdout?
   if (!ifd || FLAG(c)) ofd = 1;
@@ -134,7 +136,7 @@
     else if ((out = strend(in, ".gz"))>in) out = xstrndup(in, out-in);
     else return error_msg("no .gz: %s", in);
 
-    ofd = xcreate(out, O_CREAT|O_WRONLY|WARN_ONLY|(O_EXCL*!FLAG(f)),sb.st_mode);
+    ofd = xcreate(out, O_CREAT|O_WRONLY|WARN_ONLY|O_EXCL*!FLAG(f), sb.st_mode);
     if (ofd == -1) return;
   }
 
@@ -158,6 +160,8 @@
     if ((toys.optflags>>TT.level)&1) break;
   if (!(TT.level = 9-TT.level)) TT.level = 6;
 
+  if (FLAG(t)) toys.optflags |= FLAG_d;
+
   loopfiles(toys.optargs, do_gzip);
 }
 
diff --git a/toys/lsb/hostname.c b/toys/lsb/hostname.c
index daa60cc..3c15b86 100644
--- a/toys/lsb/hostname.c
+++ b/toys/lsb/hostname.c
@@ -66,7 +66,7 @@
     snprintf(toybuf, sizeof(toybuf), "%s", h->h_name);
   }
   dot = toybuf+strcspn(toybuf, ".");
-  if (FLAG(s)) *dot = '\0';
+  if (FLAG(s)) *dot = 0;
   xputs(FLAG(d) ? dot+1 : toybuf);
 }
 
diff --git a/toys/lsb/killall.c b/toys/lsb/killall.c
index d3546a0..d2a5dd2 100644
--- a/toys/lsb/killall.c
+++ b/toys/lsb/killall.c
@@ -50,6 +50,7 @@
   kill(pid, TT.signum);
   if (FLAG(w)) {
     struct int_list *new = xmalloc(sizeof(*TT.pids));
+
     new->val = pid;
     new->next = TT.pids;
     TT.pids = new;
diff --git a/toys/lsb/md5sum.c b/toys/lsb/md5sum.c
index feb403f..1f83a29 100644
--- a/toys/lsb/md5sum.c
+++ b/toys/lsb/md5sum.c
@@ -160,8 +160,7 @@
   unsigned x[4], *b = TT.buffer.i32;
   int i;
 
-  memcpy(x, TT.state.i32, sizeof(x));
-
+  for (i = 0; i<4; i++) x[i] = TT.state.i32[i];
   for (i = 0; i<64; i++) {
     unsigned in, a, rot, temp;
 
@@ -189,7 +188,7 @@
       rot = (5*rot)+(((rot+2)&2)>>1);
       temp = x[(a+2)&3] ^ (x[(a+1)&3] | ~x[(a+3)&3]);
     }
-    temp += x[a] + b[in] + TT.rconsttable32[i];
+    temp += x[a] + SWAP_LE32(b[in]) + TT.rconsttable32[i];
     x[a] = x[(a+1)&3] + ((temp<<rot) | (temp>>(32-rot)));
   }
   for (i = 0; i<4; i++) TT.state.i32[i] += x[i];
@@ -207,6 +206,8 @@
     oldstate[i] = TT.state.i32[i];
     rot[i] = TT.state.i32 + i;
   }
+  if (IS_BIG_ENDIAN) for (i = 0; i<16; i++) block[i] = SWAP_LE32(block[i]);
+
   // 4 rounds of 20 operations each.
   for (i = count = 0; i<4; i++) {
     for (j = 0; j<20; j++) {
@@ -454,7 +455,7 @@
   if (CFG_TOYBOX_LIBCRYPTO) do_lib_hash(fd, name);
   else do_builtin_hash(fd, name);
 
-  if (name) printf("%s  %s\n"+4*!!FLAG(b), toybuf, name);
+  if (name) printf("%s  %s\n"+4*FLAG(b), toybuf, name);
 }
 
 static void do_c_line(char *line)
diff --git a/toys/lsb/mktemp.c b/toys/lsb/mktemp.c
index 0986b4f..530a4a2 100644
--- a/toys/lsb/mktemp.c
+++ b/toys/lsb/mktemp.c
@@ -48,7 +48,7 @@
   if (!template) template = "tmp.XXXXXXXXXX";
   else {
     if (*template == '/' && TT.p && *TT.p) perror_exit("-p + /template");
-    if (!FLAG(p)&&!FLAG(t)) dir = 0;
+    if (!FLAG(p) && !FLAG(t)) dir = 0;
   }
 
   // TODO: coreutils cleans paths, so -p /t/// would result in /t/xxx...
@@ -62,14 +62,8 @@
     long long rr;
     char *s = template+len;
 
-    // Fall back to random-ish if xgetrandom fails.
-    if (!xgetrandom(&rr, sizeof(rr), WARN_ONLY)) {
-      struct timespec ts;
-
-      clock_gettime(CLOCK_REALTIME, &ts);
-      rr = ts.tv_nsec*65537+(long)template+getpid()+(long)&template;
-    }
     // Replace X with 64 chars from posix portable character set (all but "_").
+    xgetrandom(&rr, sizeof(rr));
     while (--s>template) {
       if (*s != 'X') break;
       *s = '-'+(rr&63);
diff --git a/toys/lsb/mount.c b/toys/lsb/mount.c
index 10e8e9e..109f6e1 100644
--- a/toys/lsb/mount.c
+++ b/toys/lsb/mount.c
@@ -7,9 +7,12 @@
  * Note: -hV is bad spec, haven't implemented -FsLU yet
  * no mtab (/proc/mounts does it) so -n is NOP.
  * TODO mount -o loop,autoclear (linux git 96c5865559ce)
+ * TODO mount jffs2.img dir (block2mtd)
+ * TODO fstab user
+ * TODO mount [^/]*:def = nfs, \\samba
 
-USE_MOUNT(NEWTOY(mount, "?O:afnrvwt:o*[-rw]", TOYFLAG_BIN|TOYFLAG_STAYROOT))
-//USE_NFSMOUNT(NEWTOY(nfsmount, "?<2>2", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
+USE_MOUNT(NEWTOY(mount, "?RO:afnrvwt:o*[-rw]", TOYFLAG_BIN|TOYFLAG_STAYROOT))
+//USE_NFSMOUNT(NEWTOY(nfsmount, "<2>2", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
 
 config MOUNT
   bool "mount"
@@ -57,9 +60,8 @@
 #include "toys.h"
 
 GLOBALS(
-  struct arg_list *optlist;
-  char *type;
-  char *bigO;
+  struct arg_list *o;
+  char *t, *O;
 
   unsigned long flags;
   char *opts;
@@ -72,7 +74,6 @@
 // TODO -p (passfd)
 // TODO -a -t notype,type2
 // TODO --subtree
-// TODO --rbind, -R
 // TODO make "mount --bind,ro old new" work (implicit -o remount)
 // TODO mount -a
 // TODO mount -o remount
@@ -87,15 +88,16 @@
 // TODO mount UUID=blah
 
 // Strip flags out of comma separated list of options, return flags,.
+// TODO: flip order and it's tagged array?
 static long flag_opts(char *new, long flags, char **more)
 {
   struct {
     char *name;
     long flags;
   } opts[] = {
-    // NOPs (we autodetect --loop and --bind)
-    {"loop", 0}, {"bind", 0}, {"defaults", 0}, {"quiet", 0},
+    {"loop", 0}, {"defaults", 0}, {"quiet", 0}, // NOPs
     {"user", 0}, {"nouser", 0}, // checked in fstab, ignored in -o
+    {"bind", MS_REC}, {"rbind", ~MS_REC}, // Autodetected but override defaults
     {"ro", MS_RDONLY}, {"rw", ~MS_RDONLY},
     {"nosuid", MS_NOSUID}, {"suid", ~MS_NOSUID},
     {"nodev", MS_NODEV}, {"dev", ~MS_NODEV},
@@ -145,25 +147,6 @@
   return flags;
 }
 
-// Shell out to a program, returning the output string or NULL on error
-static char *tortoise(int loud, char **cmd)
-{
-  int rc, pipe, len;
-  pid_t pid;
-
-  pid = xpopen(cmd, &pipe, 1);
-  len = readall(pipe, toybuf, sizeof(toybuf)-1);
-  rc = xpclose(pid, pipe);
-  if (!rc && len > 1) {
-    if (toybuf[len-1] == '\n') --len;
-    toybuf[len] = 0;
-    return toybuf;
-  }
-  if (loud) error_msg("%s failed %d", *cmd, rc);
-
-  return 0;
-}
-
 static void mount_filesystem(char *dev, char *dir, char *type,
   unsigned long flags, char *opts)
 {
@@ -183,15 +166,16 @@
   }
 
   if (strstart(&dev, "UUID=")) {
-    char *s = tortoise(0, (char *[]){"blkid", "-U", dev, 0});
+    char *s = chomp(xrunread((char *[]){"blkid", "-U", dev, 0}, 0));
 
-    if (!s) return error_msg("No uuid %s", dev);
-    dev = s;
+    if (!s || strlen(s)>=sizeof(toybuf)) return error_msg("No uuid %s", dev);
+    strcpy(dev = toybuf, s);
+    free(s);
   }
 
   // Autodetect bind mount or filesystem type
 
-  if (type && !strcmp(type, "auto")) type = 0;
+  if (type && (!strcmp(type, "auto") || !strcmp(type, "none"))) type = 0;
   if (flags & MS_MOVE) {
     if (type) error_exit("--move with -t");
   } else if (!type) {
@@ -202,6 +186,7 @@
         && ((S_ISREG(stdev.st_mode) && S_ISREG(stdir.st_mode))
             || (S_ISDIR(stdev.st_mode) && S_ISDIR(stdir.st_mode))))
     {
+      flags ^= MS_REC;
       flags |= MS_BIND;
     } else fp = xfopen("/proc/filesystems", "r");
   } else if (!strcmp(type, "ignore")) return;
@@ -266,10 +251,11 @@
     // device, then do the loopback setup and retry the mount.
 
     if (rc && errno == ENOTBLK) {
-      dev = tortoise(1, (char *[]){"losetup",
-        (flags&MS_RDONLY) ? "-fsr" : "-fs", dev, 0});
-      if (!dev) break;
-      continue;
+      char *losetup[] = {"losetup", (flags&MS_RDONLY)?"-fsr":"-fs", dev, 0};
+
+      if ((dev = chomp(xrunread(losetup, 0)))) continue;
+      error_msg("%s failed", *losetup);
+      break;
     }
 
     free(buf);
@@ -300,9 +286,10 @@
 
   // First pass; just accumulate string, don't parse flags yet. (This is so
   // we can modify fstab entries with -a, or mtab with remount.)
-  for (o = TT.optlist; o; o = o->next) comma_collate(&opts, o->arg);
+  for (o = TT.o; o; o = o->next) comma_collate(&opts, o->arg);
   if (FLAG(r)) comma_collate(&opts, "ro");
   if (FLAG(w)) comma_collate(&opts, "rw");
+  if (FLAG(R)) comma_collate(&opts, "rbind");
 
   // Treat each --option as -o option
   for (ss = toys.optargs; *ss; ss++) {
@@ -349,7 +336,7 @@
            if (strncmp(dev, mm->dir, len)
                || (mm->dir[len] && mm->dir[len] != '/')) continue;
         } else if (noauto) continue; // never present in the remount case
-        if (!mountlist_istype(mm,TT.type) || !comma_scanall(mm->opts,TT.bigO))
+        if (!mountlist_istype(mm, TT.t) || !comma_scanall(mm->opts, TT.O))
           continue;
       } else {
         if (dir && strcmp(dir, mm->dir)) continue;
@@ -388,7 +375,7 @@
     for (mtl = xgetmountlist(0); mtl && (mm = dlist_pop(&mtl)); free(mm)) {
       char *s = 0;
 
-      if (TT.type && strcmp(TT.type, mm->type)) continue;
+      if (TT.t && strcmp(TT.t, mm->type)) continue;
       if (*mm->device == '/') s = xabspath(mm->device, 0);
       xprintf("%s on %s type %s (%s)\n",
               s ? s : mm->device, mm->dir, mm->type, mm->opts);
@@ -400,7 +387,7 @@
     char *more = 0;
 
     flags = flag_opts(opts, flags, &more);
-    mount_filesystem(dev, dir, TT.type, flags, more);
+    mount_filesystem(dev, dir, TT.t, flags, more);
     if (CFG_TOYBOX_FREE) free(more);
   }
 }
diff --git a/toys/lsb/passwd.c b/toys/lsb/passwd.c
index 8c17dc6..6c822e8 100644
--- a/toys/lsb/passwd.c
+++ b/toys/lsb/passwd.c
@@ -10,7 +10,6 @@
 config PASSWD
   bool "passwd"
   default y
-  depends on TOYBOX_SHADOW
   help
     usage: passwd [-a ALGO] [-dlu] [USER]
 
diff --git a/toys/lsb/seq.c b/toys/lsb/seq.c
index 7a931c6..b44d05c 100644
--- a/toys/lsb/seq.c
+++ b/toys/lsb/seq.c
@@ -52,24 +52,6 @@
   return xstrtod(s);
 }
 
-// fast integer conversion to decimal string
-// TODO move to lib?
-static char *itoa(char *s, int i)
-{
-  char buf[16], *ff = buf;
-  unsigned n = i;
-
-  if (i<0) {
-    *s++ = '-';
-    n = -i;
-  }
-  do *ff++ = '0'+n%10; while ((n /= 10));
-  do *s++ = *--ff; while (ff>buf);
-  *s++ = '\n';
-
-  return s;
-}
-
 static char *flush_toybuf(char *ss)
 {
   if (ss-toybuf<TT.buflen) return ss;
@@ -80,9 +62,9 @@
 
 void seq_main(void)
 {
-  char fbuf[32], *ss;
+  char fbuf[64], *ss;
   double first = 1, increment = 1, last, dd;
-  int ii, inc = 1, len, slen;
+  long ii, inc = 1, len, slen;
 
   // parse arguments
   if (!TT.s) TT.s = "\n";
@@ -101,20 +83,20 @@
     slen = dd;
     if (dd != slen) inc = 0;
   }
-  if (!FLAG(f)) sprintf(TT.f = fbuf, "%%0%d.%df", len, TT.precision);
-  TT.buflen = sizeof(toybuf) - 32 - len - TT.precision - strlen(TT.s);
+  if (!FLAG(f)) sprintf(TT.f = fbuf, "%%0%ld.%df", len, TT.precision);
+  TT.buflen = sizeof(toybuf)-sizeof(fbuf)-len-TT.precision-strlen(TT.s);
   if (TT.buflen<0) error_exit("bad -s");
 
-  // fast path: when everything fits in an int with no flags.
+  // fast path: when everything fits in a long with no flags.
   if (!toys.optflags && inc) {
     ii = first;
     len = last;
     inc = increment;
     ss = toybuf;
     if (inc>0) for (; ii<=len; ii += inc)
-      ss = flush_toybuf(itoa(ss, ii));
+      ss = flush_toybuf(ss+sprintf(ss, "%ld\n", ii));
     else if (inc<0) for (; ii>=len; ii += inc)
-      ss = flush_toybuf(itoa(ss, ii));
+      ss = flush_toybuf(ss+sprintf(ss, "%ld\n", ii));
     if (ss != toybuf) xwrite(1, toybuf, ss-toybuf);
 
     return;
diff --git a/toys/lsb/su.c b/toys/lsb/su.c
index 136e81e..71df8a6 100644
--- a/toys/lsb/su.c
+++ b/toys/lsb/su.c
@@ -12,7 +12,6 @@
 config SU
   bool "su"
   default y
-  depends on TOYBOX_SHADOW
   help
     usage: su [-lp] [-u UID] [-g GID,...] [-s SHELL] [-c CMD] [USER [COMMAND...]]
 
@@ -46,7 +45,6 @@
 {
   char *name, *passhash = 0, **argu, **argv;
   struct passwd *up;
-  struct spwd *shp;
 
   if (*toys.optargs && !strcmp("-", *toys.optargs)) {
     toys.optflags |= FLAG_l;
@@ -58,8 +56,10 @@
 
   loggit(LOG_NOTICE, "%s->%s", getusername(geteuid()), name);
 
-  if (!(shp = getspnam(name))) perror_exit("no '%s'", name);
   if (getuid()) {
+    struct spwd *shp;
+
+    if (!(shp = getspnam(name))) perror_exit("no '%s'", name);
     if (*shp->sp_pwdp != '$') goto deny;
     if (read_password(toybuf, sizeof(toybuf), "Password: ")) goto deny;
     passhash = crypt(toybuf, shp->sp_pwdp);
diff --git a/toys/lsb/umount.c b/toys/lsb/umount.c
index 3c9e3ca..fbaa8e4 100644
--- a/toys/lsb/umount.c
+++ b/toys/lsb/umount.c
@@ -37,7 +37,7 @@
   char *types;
 )
 
-// todo (done?)
+// TODO (done?)
 //   borrow df code to identify filesystem?
 //   umount -a from fstab
 //   umount when getpid() not 0, according to fstab
diff --git a/toys/net/host.c b/toys/net/host.c
index 2033167..f8e54dc 100644
--- a/toys/net/host.c
+++ b/toys/net/host.c
@@ -38,9 +38,9 @@
   int type;
 } rrt[] = { { "A", "has address", 1 }, { "NS", "name server", 2 },
   { "CNAME", "is a nickname for", 5 }, { "SOA", "start of authority", 6 },
-  { "PTR", "domain name pointer", 12 }, { "MX", "mail is handled", 15 },
-  { "TXT", "descriptive text", 16 }, { "AAAA", "has address", 28 },
-  { "SRV", "mail is handled", 33 }
+  { "PTR", "domain name pointer", 12 }, { "HINFO", "host information", 13 },
+  { "MX", "mail is handled", 15 }, { "TXT", "descriptive text", 16 },
+  { "AAAA", "has address", 28 }, { "SRV", "mail is handled", 33 }
 };
 
 int xdn_expand(char *packet, char *endpkt, char *comp, char *expand, int elen)
@@ -97,7 +97,7 @@
 
   // Prepare query packet of appropriate type
   if (TT.t[0]-'0'<10) type = atoi(TT.t); // TODO
-  else if (!strcasecmp(TT.t, "any") || strcmp(TT.t, "*")) type = 255;
+  else if (!strcasecmp(TT.t, "any") || !strcmp(TT.t, "*")) type = 255;
   else {
     for (i = 0; i<ARRAY_LEN(rrt); i++) if (!strcasecmp(TT.t, rrt[i].name)) {
       type = rrt[i].type;
@@ -139,6 +139,7 @@
 
   // Print the result
   p = abuf + 12;
+  qlen = 0;
   for (sec = 0; sec<(2<<verbose); sec++) {
     count = peek_be(abuf+4+2*sec, 2);
     if (verbose && count>0 && sec>1) 
@@ -156,11 +157,11 @@
       pllen = peek_be(p, 2);
       p += 2;
       if ((p-abuf)+pllen>alen) error_exit("tilt");
-
       if (type==1 || type == 28)
         inet_ntop(type==1 ? AF_INET : AF_INET6, p, t2, t2len);
       else if (type==2 || type==5) xdn_expand(abuf, abuf+alen, p, t2, t2len);
-      else if (type==16) sprintf(t2, "\"%.*s\"", minof(pllen, t2len), p);
+      else if (type==13 || type==16)
+        sprintf(t2, "\"%.*s\"", minof(pllen, t2len), p);
       else if (type==6) { 
         ss = p+xdn_expand(abuf, abuf+alen, p, t2, t2len-1);
         j = strlen(t2);
@@ -184,12 +185,13 @@
         printf("%s unsupported RR type %u\n", toybuf, type);
         continue;
       }
-
       for (i = 0; rrt[i].type != type; i++);
       if (verbose) printf("%s\t%u\tIN %s\t%s\n", toybuf, ttl, rrt[i].name, t2);
-      else printf("%s %s %s\n", toybuf, rrt[type].msg, t2);
+      else printf("%s %s %s\n", toybuf, rrt[i].msg, t2);
+      qlen++;
     }
   }
+  if (TT.t && !qlen) printf("%s has no %s record\n", *toys.optargs, TT.t);
 
   if (CFG_TOYBOX_FREE) free(abuf);
   toys.exitval = rcode;
diff --git a/toys/net/httpd.c b/toys/net/httpd.c
new file mode 100644
index 0000000..3cb7842
--- /dev/null
+++ b/toys/net/httpd.c
@@ -0,0 +1,201 @@
+/* httpd.c - Web server.
+ *
+ * Copyright 2022 Rob Landley <rob@landley.net>
+ *
+ * See https://www.ietf.org/rfc/rfc2616.txt
+ *
+ * TODO: multiple domains, https, actual inetd with ratelimit...
+ * range, gzip, ETag (If-None-Match:, Last-Modified:), Date:
+ * "Accept-Ranges: bytes"/"Range: bytes=xxx-[yyy]"
+ * .htaccess (auth, forward)
+ * optional conf file, error pages
+ * -ifv -p [IP:]PORT -u [USER][:GRP] -c CFGFILE
+ * cgi: SERVER_PORT SERVER_NAME REMOTE_ADDR REMOTE_HOST REQUEST_METHOD
+
+USE_HTTPD(NEWTOY(httpd, ">1v", TOYFLAG_USR|TOYFLAG_BIN))
+
+config HTTPD
+  bool "httpd"
+  default y
+  help
+    usage: httpd [-e STR] [DIR]
+
+    Serve contents of directory as static web pages.
+
+    -e	Escape STR as URL, printing result and exiting.
+    -d	Decode escaped STR, printing result and exiting.
+    -v	Verbose
+*/
+
+#define FOR_httpd
+#include "toys.h"
+
+char *rfc1123(char *buf, time_t t)
+{
+  strftime(buf, 64, "%a, %d %b %Y %T GMT", gmtime(&t));
+
+  return buf;
+}
+
+// She never told me...
+char *mime(char *file)
+{
+  char *s = strrchr(file, '.'), *types[] = {
+    "asc\0text/plain", "bin\0application/octet-stream", "bmp\0image/bmp",
+    "cpio\0application/x-cpio", "css\0text/css", "doc\0application/msword",
+    "dtd\0text/xml", "dvi\0application/x-dvi", "gif\0image/gif",
+    "htm\0text/html", "html\0text/html", "jar\0applicat/x-java-archive",
+    "jpeg\0image/jpeg", "jpg\0image/jpeg", "js\0application/x-javascript",
+    "mp3\0audio/mpeg", "mp4\0video/mp4", "mpg\0video/mpeg",
+    "ogg\0application/ogg", "pbm\0image/x-portable-bitmap",
+    "pdf\0application/pdf", "png\0image/png",
+    "ppt\0application/vnd.ms-powerpoint", "ps\0application/postscript",
+    "rtf\0text/rtf", "sgml\0text/sgml", "svg\0image/svg+xml",
+    "tar\0application/x-tar", "tex\0application/x-tex", "tiff\0image/tiff",
+    "txt\0text/plain", "wav\0audio/x-wav", "xls\0application/vnd.ms-excel",
+    "xml\0tet/xml", "zip\0application/zip"
+  };
+  int i;
+
+  strcpy(toybuf, "text/plain");
+  if (s++) for (i = 0; i<ARRAY_LEN(types); i++) {
+    if (strcasecmp(s, types[i])) continue;
+    strcpy(toybuf, types[i]+strlen(types[i])+1);
+    break;
+  }
+  if (!strncmp(toybuf, "text/", 5)) strcat(toybuf, "; charset=UTF-8");
+
+  return toybuf;
+}
+
+// Stop: header time.
+static void header_time(int stat, char *str, char *more)
+{
+  char buf[64];
+
+  if (!more) more = "";
+  if (FLAG(v)) dprintf(2, "REPLY: %d %s\n%s\n", stat, str, more);
+  xprintf("HTTP/1.1 %d %s\r\nServer: toybox httpd/%s\r\nDate: %s\r\n%s"
+    "Connection: close\r\n\r\n", stat, str, TOYBOX_VERSION,
+    rfc1123(buf, time(0)), more);
+}
+
+static void error_time(int stat, char *str)
+{
+  header_time(stat, str, 0);
+  xprintf("<html><head><title>%d %s</title></head>"
+    "<body><h3>%d %s</h3></body></html>", stat, str, stat, str);
+}
+
+static int isunder(char *file, char *dir)
+{
+  char *s1 = xabspath(dir, ABS_FILE), *s2 = xabspath(file, 0), *ss = s2;
+  int rc = s1 && s2 && strstart(&ss, s1) && (!*ss || *ss=='/' || ss[-1]=='/');
+
+  free(s2);
+  free(s1);
+
+  return rc;
+}
+
+// Handle a connection on fd
+void handle(int infd, int outfd)
+{
+  FILE *fp = fdopen(infd, "r");
+  char *s = xgetline(fp), *cut, *ss, *esc, *path, *word[3];
+  int i = sizeof(toybuf), fd;
+
+  if (!s) return;
+
+  if (!getsockname(0, (void *)&toybuf, &i)) {
+    if (FLAG(v))
+      dprintf(2, "Hello %s\n%s\n", ntop((void *)toybuf), s);
+  }
+
+  // Split line into method/path/protocol
+  for (i = 0, ss = s;;) {
+    word[i++] = ss;
+    while (*ss && !strchr(" \r\n", *ss)) ss++;
+    while (*ss && strchr(" \r\n", *ss)) *(ss++) = 0;
+    if (i==3) break;
+    if (!*ss) return header_time(400, "Bad Request", 0);
+  }
+
+  // Process additional http/1.1 lines
+  while ((ss = xgetline(fp))) {
+    i = *chomp(ss);
+    if (FLAG(v)) dprintf(2, "%s\n", ss);
+// TODO: any of
+//User-Agent: Wget/1.20.1 (linux-gnu) - do we want to log anything?
+//Accept: */* - 406 Too Snobbish
+//Accept-Encoding: identity - we can gzip?
+//Host: landley.net  - we could handle multiple domains?
+//Connection: Keep-Alive - probably don't care
+
+    free(ss);
+    if (!i) break;
+  }
+
+  if (!strcasecmp(word[0], "get")) {
+    struct stat st;
+
+    if (*(ss = word[1])!='/') error_time(400, "Bad Request");
+    while (*ss=='/') ss++;
+    if (!*ss) ss = "./";
+    else if ((cut = unescape_url(ss, 1))) setenv("QUERY_STRING", cut, 1);
+
+    // TODO domain.com:/path/to/blah domain2.com:/path/to/that
+    // TODO cgi PATH_INFO /path/to/filename.cgi/and/more/stuff?path&info
+    if (!isunder(ss, ".") || stat(ss, &st)) error_time(404, "Not Found");
+    else if (-1 == (fd = open(ss, O_RDONLY))) error_time(403, "Forbidden");
+    else if (!S_ISDIR(st.st_mode)) {
+      char buf[64];
+file:
+      header_time(200, "Ok", ss = xmprintf("Content-Type: %s\r\n"
+        "Content-Length: %lld\r\nLast-Modified: %s\r\n",
+        mime(ss), (long long)st.st_size, rfc1123(buf, st.st_mtime)));
+      free(ss);
+      xsendfile(fd, outfd);
+    } else if (ss[strlen(ss)-1]!='/') {
+      header_time(302, "Found", path = xmprintf("Location: %s/\r\n", word[1]));
+      free(path);
+    } else {
+      DIR *dd;
+      struct dirent *dir;
+
+      // Do we have an index.html?
+      path = ss;
+      ss = "index.html";
+      path = xmprintf("%s%s", path, ss);
+      if (stat(path, &st) || !S_ISREG(st.st_mode)) i = -1;
+      else if (-1 == (i = open(path, O_RDONLY))) error_time(403, "Forbidden");
+      free(path);
+      if (i != -1) {
+        close(fd);
+        fd = i;
+
+        goto file;
+      }
+
+      // List directory contents
+      header_time(200, "Ok", "Content-Type: text/html\r\n");
+      dprintf(outfd, "<html><head><title>Index of %s</title></head>\n"
+        "<body><h3>Index of %s</h3></body>\n", word[1], word[1]);
+      for (dd = fdopendir(fd); (dir = readdir(dd));) {
+        esc = escape_url(dir->d_name, "<>&\"");
+        dprintf(outfd, "<a href=\"%s\">%s</a><br />\n", esc, esc);
+        free(esc);
+      }
+      dprintf(outfd, "</body></html>\n");
+    }
+  } else error_time(501, "Not Implemented");
+  free(s);
+}
+
+void httpd_main(void)
+{
+  if (toys.optc && chdir(*toys.optargs))
+    return error_time(500, "Internal Error");
+  // inetd only at the moment
+  handle(0, 1);
+}
diff --git a/toys/net/netcat.c b/toys/net/netcat.c
index 2d80a18..3834894 100644
--- a/toys/net/netcat.c
+++ b/toys/net/netcat.c
@@ -2,47 +2,35 @@
  *
  * Copyright 2007 Rob Landley <rob@landley.net>
  *
- * TODO: udp, ipv6, genericize for telnet/microcom/tail-f
- * fix -t, xconnect
- * netcat -L zombies
+ * TODO: genericize for telnet/microcom/tail-f, fix -t
 
+USE_NETCAT(NEWTOY(netcat, "^tElLw#<1W#<1p#<1>65535q#<1s:f:46uUn[!tlL][!Lw][!Lu][!46U]", TOYFLAG_BIN))
 USE_NETCAT(OLDTOY(nc, netcat, TOYFLAG_USR|TOYFLAG_BIN))
-USE_NETCAT(NEWTOY(netcat, USE_NETCAT_LISTEN("^tElL")"w#<1W#<1p#<1>65535q#<1s:f:46uU"USE_NETCAT_LISTEN("[!tlL][!Lw]")"[!46U]", TOYFLAG_BIN))
 
 config NETCAT
   bool "netcat"
   default y
   help
-    usage: netcat [-46U] [-u] [-wpq #] [-s addr] {IPADDR PORTNUM|-f FILENAME|COMMAND...}
+    usage: netcat [-46ElLtUu] [-wpq #] [-s addr] {IPADDR PORTNUM|-f FILENAME|COMMAND...}
 
     Forward stdin/stdout to a file or network connection.
 
     -4	Force IPv4
     -6	Force IPv6
+    -E	Forward stderr
     -f	Use FILENAME (ala /dev/ttyS0) instead of network
+    -l	Listen for one incoming connection, then exit
+    -L	Listen and background each incoming connection (server mode)
+    -n	No DNS lookup
     -p	Local port number
     -q	Quit SECONDS after EOF on stdin, even if stdout hasn't closed yet
     -s	Local source address
+    -t	Allocate tty
     -u	Use UDP
     -U	Use a UNIX domain socket
     -w	SECONDS timeout to establish connection
     -W	SECONDS timeout for more data on an idle connection
 
-    Use "stty 115200 -F /dev/ttyS0 && stty raw -echo -ctlecho" with
-    netcat -f to connect to a serial port.
-
-config NETCAT_LISTEN
-  bool "netcat server options (-let)"
-  default y
-  depends on NETCAT
-  help
-    usage: netcat [-tElL]
-
-    -l	Listen for one incoming connection, then exit
-    -L	Listen and background each incoming connection (server mode)
-    -t	Allocate tty
-    -E	Forward stderr
-
     When listening the COMMAND line is executed as a child process to handle
     an incoming connection. With no COMMAND -l forwards the connection
     to stdin/stdout. If no -p specified, -l prints the port it bound to and
@@ -50,6 +38,9 @@
 
     For a quick-and-dirty server, try something like:
     netcat -s 127.0.0.1 -p 1234 -tL sh -l
+
+    Or use "stty 115200 -F /dev/ttyS0 && stty raw -echo -ctlecho" with
+    netcat -f to connect to a serial port.
 */
 
 #define FOR_netcat
@@ -66,12 +57,6 @@
   xexit();
 }
 
-static void set_alarm(int seconds)
-{
-  xsignal(SIGALRM, seconds ? timeout : SIG_DFL);
-  alarm(seconds);
-}
-
 // open AF_UNIX socket
 static int usock(char *name, int type, int out)
 {
@@ -90,12 +75,12 @@
 
   return sockfd;
 }
- 
 
 void netcat_main(void)
 {
   int sockfd = -1, in1 = 0, in2 = 0, out1 = 1, out2 = 1, family = AF_UNSPEC,
-    ll = FLAG(L)|FLAG(l), type = FLAG(u) ? SOCK_DGRAM : SOCK_STREAM;
+    type = FLAG(u) ? SOCK_DGRAM : SOCK_STREAM;
+  socklen_t len;
   pid_t child;
 
   // Addjust idle and quit_delay to ms or -1 for no timeout
@@ -103,11 +88,14 @@
   TT.q = TT.q ? TT.q*1000 : -1;
 
   xsignal(SIGCHLD, SIG_IGN);
-  set_alarm(TT.w);
+  if (TT.w) {
+    xsignal(SIGALRM, timeout);
+    alarm(TT.w);
+  }
 
   // The argument parsing logic can't make "<2" conditional on other
   // arguments like -f and -l, so do it by hand here.
-  if (FLAG(f) ? toys.optc : (!ll && toys.optc!=(FLAG(U)?1:2)))
+  if (FLAG(f) ? toys.optc : (!FLAG(l) && !FLAG(L) && toys.optc!=2-FLAG(U)))
     help_exit("bad argument count");
 
   if (FLAG(4)) family = AF_INET;
@@ -117,13 +105,13 @@
   if (TT.f) in1 = out2 = xopen(TT.f, O_RDWR);
   else {
     // Setup socket
-    if (!ll) {
+    if (!FLAG(l) && !FLAG(L)) {
       if (FLAG(U)) sockfd = usock(toys.optargs[0], type, 1);
-      else sockfd = xconnectany(xgetaddrinfo(toys.optargs[0], toys.optargs[1],
-                                          family, type, 0, 0));
+      else sockfd = xconnectany(xgetaddrinfo(toys.optargs[0],
+        toys.optargs[1], family, type, 0, AI_NUMERICHOST*FLAG(n)));
 
       // We have a connection. Disarm timeout and start poll/send loop.
-      set_alarm(0);
+      alarm(0);
       in1 = out2 = sockfd;
       pollinate(in1, in2, out1, out2, TT.W, TT.q);
     } else {
@@ -136,12 +124,12 @@
         sockfd = xbindany(xgetaddrinfo(TT.s, toybuf, family, type, 0, 0));
       }
 
-      if (listen(sockfd, 5)) error_exit("listen");
+      if (!FLAG(u) && listen(sockfd, 5)) perror_exit("listen");
       if (!TT.p && !FLAG(U)) {
         struct sockaddr* address = (void*)toybuf;
-        socklen_t len = sizeof(struct sockaddr_storage);
         short port_be;
 
+        len = sizeof(struct sockaddr_storage);
         getsockname(sockfd, address, &len);
         if (address->sa_family == AF_INET)
           port_be = ((struct sockaddr_in*)address)->sin_port;
@@ -156,41 +144,46 @@
       }
 
       do {
+       len = sizeof(struct sockaddr_storage);
+        if (FLAG(u)) {
+          if (-1 == recvfrom(in1 = dup(sockfd), &child, 1, MSG_PEEK,
+            (void *)toybuf, &len)) perror_exit("recvfrom");
+        } else if ((in1 = accept(sockfd, 0, 0))<0) perror_exit("accept");
+        out2 = in1;
         child = 0;
-        in1 = out2 = accept(sockfd, 0, 0);
-        if (in1<0) perror_exit("accept");
 
         // We have a connection. Disarm timeout.
-        set_alarm(0);
+        alarm(0);
 
+        // Fork a child as necessary. Parent cleans up and continues here.
+        if (toys.optc && FLAG(L)) NOEXIT(child = XVFORK());
+        if (child) {
+          close(in1);
+          continue;
+        }
+
+        if (FLAG(u))
+          xconnect(in1, (void *)toybuf, sizeof(struct sockaddr_storage));
+
+        // Cleanup and redirect for exec
         if (toys.optc) {
           // Do we need a tty?
+// TODO nommu and -t only affects server mode...
+//        if (FLAG(t)) child = forkpty(&fdout, NULL, NULL, NULL);
 
-// TODO nommu, and -t only affects server mode...? Only do -t with optc
-//        if (CFG_TOYBOX_FORK && (toys.optflags&FLAG_t))
-//          child = forkpty(&fdout, NULL, NULL, NULL);
-//        else
-
-          // Do we need to fork and/or redirect for exec?
-
-// TODO xpopen_both() here?
-
-          if (FLAG(L)) NOEXIT(child = XVFORK());
-          if (child) {
-            close(in1);
-            continue;
-          }
           close(sockfd);
           dup2(in1, 0);
           dup2(in1, 1);
           if (FLAG(E)) dup2(in1, 2);
           if (in1>2) close(in1);
           xexec(toys.optargs);
-        }
 
-        pollinate(in1, in2, out1, out2, TT.W, TT.q);
-        close(in1);
-      } while (!FLAG(l));
+        // Copy stdin/out
+        } else {
+          pollinate(in1, in2, out1, out2, TT.W, TT.q);
+          close(in1);
+        }
+      } while (FLAG(L));
     }
   }
 
diff --git a/toys/net/netstat.c b/toys/net/netstat.c
index 7eed02d..9470e8e 100644
--- a/toys/net/netstat.c
+++ b/toys/net/netstat.c
@@ -36,6 +36,42 @@
   int wpad;
 )
 
+struct num_cache {
+  struct num_cache *next;
+  long long num;
+  char data[];
+};
+
+// Find num in cache
+static struct num_cache *get_num_cache(struct num_cache *cache, long long num)
+{
+  while (cache) {
+    if (num==cache->num) return cache;
+    cache = cache->next;
+  }
+
+  return 0;
+}
+
+// Uniquely add num+data to cache. Updates *cache, returns pointer to existing
+// entry if it was already there.
+static struct num_cache *add_num_cache(struct num_cache **cache, long long num,
+  void *data, int len)
+{
+  struct num_cache *old = get_num_cache(*cache, num);
+
+  if (old) return old;
+
+  old = xzalloc(sizeof(struct num_cache)+len);
+  old->next = *cache;
+  old->num = num;
+  memcpy(old->data, data, len);
+
+  *cache = old;
+
+  return 0;
+}
+
 static void addr2str(int af, void *addr, unsigned port, char *buf, int len,
   char *proto)
 {
diff --git a/toys/net/sntp.c b/toys/net/sntp.c
index 1139b0e..4a216df 100644
--- a/toys/net/sntp.c
+++ b/toys/net/sntp.c
@@ -20,10 +20,10 @@
     -s	Set system clock suddenly
     -a	Adjust system clock gradually
     -S	Serve time instead of querying (bind to SERVER address if specified)
-    -m	Wait for updates from multicast ADDRESS (RFC 4330 default 224.0.1.1)
-    -M	Multicast server on ADDRESS (default 224.0.0.1)
+    -m	Wait for updates from multicast ADDRESS (RFC 4330 suggests 224.0.1.1)
+    -M	Multicast server on ADDRESS (RFC 4330 suggests 224.0.1.1)
     -t	TTL (multicast only, default 1)
-    -d	Daemonize (run in background re-querying )
+    -d	Daemonize (run in background re-querying)
     -D	Daemonize but stay in foreground: re-query time every 1000 seconds
     -r	Retry shift (every 1<<SHIFT seconds)
     -q	Quiet (don't display time)
diff --git a/toys/net/tunctl.c b/toys/net/tunctl.c
index 6a2cf1e..1285570 100644
--- a/toys/net/tunctl.c
+++ b/toys/net/tunctl.c
@@ -7,7 +7,7 @@
  * This is useful for things like "kvm -netdev tap" and containers.
  * See https://landley.net/lxc/02-networking.html for example usage.
  *
- * todo: bridge mode 
+ * TODO: bridge mode 
  *  -b	bridge daemon (forwards packets between NAME and NAME2 interfaces)
 
 
diff --git a/toys/pending/wget.c b/toys/net/wget.c
similarity index 85%
rename from toys/pending/wget.c
rename to toys/net/wget.c
index 9e100e8..4e17309 100644
--- a/toys/pending/wget.c
+++ b/toys/net/wget.c
@@ -21,16 +21,16 @@
  * Transfer Encoding [gzip|deflate]: https://jigsaw.w3.org/HTTP/TE/bar.txt
  *
  *
- * todo: Add support for configurable TLS versions
- * todo: Add support for ftp
- * todo: Add support for Transfer Encoding (gzip|deflate)
- * todo: Add support for RFC5987
+ * TODO: Add support for configurable TLS versions
+ * TODO: Add support for ftp
+ * TODO: Add support for Transfer Encoding (gzip|deflate)
+ * TODO: Add support for RFC5987
 
 USE_WGET(NEWTOY(wget, "<1>1(max-redirect)#<0=20d(debug)O(output-document):p(post-data):", TOYFLAG_USR|TOYFLAG_BIN))
 
 config WGET
   bool "wget"
-  default n
+  default y
   help
     usage: wget [OPTIONS]... [URL]
         --max-redirect          maximum redirections allowed
@@ -44,17 +44,12 @@
 config WGET_LIBTLS
   bool "Enable HTTPS support for wget via LibTLS"
   default n
-  depends on WGET && !WGET_OPENSSL
+  depends on WGET && !TOYBOX_LIBCRYPTO
   help
     Enable HTTPS support for wget by linking to LibTLS.
     Supports using libtls, libretls or libtls-bearssl.
 
-config WGET_OPENSSL
-  bool "Enable HTTPS support for wget via OpenSSL"
-  default n
-  depends on WGET && !WGET_LIBTLS
-  help
-    Enable HTTPS support for wget by linking to OpenSSL.
+    Use TOYBOX_LIBCRYPTO to enable HTTPS support via OpenSSL.
 */
 
 #define FOR_wget
@@ -63,7 +58,7 @@
 #if CFG_WGET_LIBTLS
 #define WGET_SSL 1
 #include <tls.h>
-#elif CFG_WGET_OPENSSL
+#elif CFG_TOYBOX_LIBCRYPTO
 #define WGET_SSL 1
 #include <openssl/crypto.h>
 #include <openssl/ssl.h>
@@ -82,7 +77,7 @@
   char *url;
 #if CFG_WGET_LIBTLS
   struct tls *tls;
-#elif CFG_WGET_OPENSSL
+#elif CFG_TOYBOX_LIBCRYPTO
   struct ssl_ctx_st *ctx;
   struct ssl_st *ssl;
 #endif
@@ -94,14 +89,13 @@
   char *ss = url;
 
   // Must start with case insensitive http:// or https://
-  if (strncmp(url, "http", 4)) url = 0;
+  if (strncasecmp(url, "http", 4)) url = 0;
   else {
     url += 4;
     if ((TT.https = WGET_SSL && toupper(*url=='s'))) url++;
     if (!strstart(&url, "://")) url = 0;
   }
   if (!url) error_exit("unsupported protocol: %s", ss);
-
   if ((*path = strchr(*host = url, '/'))) *((*path)++) = 0;
   else *path = "";
 
@@ -109,7 +103,7 @@
   if (**host=='[' && (ss = strchr(++*host, ']'))) {
     *ss++ = 0;
     *port = (*ss==':') ? ++ss : 0;
-  } else if ((*port = strchr(*host, ':'))) *(*port++) = 0;
+  } else if ((*port = strchr(*host, ':'))) *((*port)++) = 0;
   if (!*port) *port = HTTPS ? "443" : "80";
 }
 
@@ -135,7 +129,7 @@
 
     if (tls_connect(TT.tls, host, port))
       error_exit("tls_connect: %s", tls_error(TT.tls));
-#elif CFG_WGET_OPENSSL
+#elif CFG_TOYBOX_LIBCRYPTO
     SSL_library_init();
     OpenSSL_add_all_algorithms();
     SSL_load_error_strings();
@@ -172,7 +166,7 @@
 
 #if CFG_WGET_LIBTLS
     if ((ret = tls_read(TT.tls, buf, len))<0) err = tls_error(TT.tls);
-#elif CFG_WGET_OPENSSL
+#elif CFG_TOYBOX_LIBCRYPTO
     if ((ret = SSL_read(TT.ssl, buf, len))<0)
       err = ERR_error_string(ERR_get_error(), 0);
 #endif
@@ -190,7 +184,7 @@
 
 #if CFG_WGET_LIBTLS
     if (len != tls_write(TT.tls, buf, len)) err = tls_error(TT.tls);
-#elif CFG_WGET_OPENSSL
+#elif CFG_TOYBOX_LIBCRYPTO
     if (len != SSL_write(TT.ssl, buf, len))
       err = ERR_error_string(ERR_get_error(), 0);
 #endif
@@ -211,7 +205,7 @@
     tls_free(TT.tls);
     TT.tls = 0;
   }
-#elif CFG_WGET_OPENSSL
+#elif CFG_TOYBOX_LIBCRYPTO
   if (TT.ssl) {
     SSL_shutdown(TT.ssl);
     SSL_free(TT.ssl);
@@ -227,25 +221,21 @@
 
 static char *wget_find_header(char *header, char *val)
 {
-  char *result = strcasestr(header, val);
+  if (!(header = strcasestr(header, val))) return 0;
+  header += strlen(val);
 
-  if (result) {
-    result += strlen(val);
-    result[strcspn(result, "\r\n")] = 0;
-  }
-
-  return result;
+  return xstrndup(header, strcspn(header, "\r\n"));
 }
 
 void wget_main(void)
 {
   long status = 0;
   size_t len, c_len = 0;
-  int fd = 0;
-  char *body, *index, *host, *port, *path, *chunked, *ss;
+  int fd = 0, ii;
+  char *body, *index, *host, *port, *path = 0, *chunked, *ss;
   char agent[] = "toybox wget/" TOYBOX_VERSION;
 
-  TT.url = xstrdup(*toys.optargs);
+  TT.url = escape_url(*toys.optargs, 0);
 
   // Ask server for URL, following redirects until success
   while (status != 200) {
@@ -253,10 +243,10 @@
 
     // Connect and write request
     wget_info(TT.url, &host, &port, &path);
-    if (TT.p) sprintf(toybuf, "Content-Length: %ld\r\n", strlen(TT.p));
+    if (TT.p) sprintf(toybuf, "Content-Length: %ld\r\n", (long)strlen(TT.p));
     ss = xmprintf("%s /%s HTTP/1.1\r\nHost: %s\r\nUser-Agent: %s\r\n"
                   "Connection: close\r\n%s\r\n%s", FLAG(p) ? "POST" : "GET",
-                  path, host, agent, FLAG(p) ? toybuf : "", FLAG(p)?TT.p:"");
+                  path, host, agent, TT.p ? toybuf : "", TT.p ? : "");
     if (FLAG(d)) printf("--- Request\n%s", ss);
     wget_connect(host, port);
     wget_write(ss, strlen(ss));
@@ -280,17 +270,34 @@
       if (!(ss = wget_find_header(toybuf, "Location: ")))
         error_exit("bad redirect");
       free(TT.url);
-      TT.url = xstrdup(ss);
+      TT.url = ss;
       wget_close();
-    } else if (status != 200) error_exit("response: %ld", status);
+    } else if (status != 200) error_exit("response %ld", status);
   }
 
   // Open output file
   if (TT.O && !strcmp(TT.O, "-")) fd = 1;
   else if (!TT.O) {
     ss = wget_find_header(toybuf, "Content-Disposition: attachment; filename=");
-    if (!ss && strchr(path, '/')) ss = getbasename(path);
-    if (!ss || !*ss ) ss = "index.html";
+    if (ss) {
+      unescape_url(ss, 1);
+      for (ii = strlen(ss); ii; ii--) {
+        if (ss[ii]=='/') memmove(ss, ss+ii, strlen(ss+ii));
+        break;
+      }
+      if (!*ss) {
+        free(ss);
+        ss = 0;
+      }
+    }
+    if (!ss) {
+      path = 0;
+      for (ii = 0, ss = *toys.optargs; *ss && *ss!='?' && *ss!='#'; ss++)
+        if (*ss=='/' && ++ii>2) path = ss+1;
+      ss = (path && ss>path) ? xstrndup(path, ss-path) : 0;
+      // TODO: handle %20 style escapes
+    }
+    if (!ss) ss = "index.html";
     if (!access((TT.O = ss), F_OK)) error_exit("%s already exists", TT.O);
   }
   // TODO: don't allow header/basename to write to stdout
diff --git a/toys/other/base64.c b/toys/other/base64.c
index 22652fd..e6c936b 100644
--- a/toys/other/base64.c
+++ b/toys/other/base64.c
@@ -4,9 +4,9 @@
  *
  * See https://tools.ietf.org/html/rfc4648
 
-// These optflags have to match. Todo: cleanup and collapse together?
-USE_BASE64(NEWTOY(base64, "diw#<0=76[!dw]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_BASE32(NEWTOY(base32, "diw#<0=76[!dw]", TOYFLAG_USR|TOYFLAG_BIN))
+// These optflags have to match. TODO: cleanup and collapse together?
+USE_BASE64(NEWTOY(base64, "diw#<0=76[!dw]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
+USE_BASE32(NEWTOY(base32, "diw#<0=76[!dw]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
 
 config BASE64
   bool "base64"
@@ -39,6 +39,7 @@
 
 GLOBALS(
   long w;
+
   unsigned total;
   unsigned n;  // number of bits used in encoding. 5 for base32, 6 for base64
   unsigned align;  // number of bits to align to
diff --git a/toys/other/blkid.c b/toys/other/blkid.c
index 01b5971..bed20b2 100644
--- a/toys/other/blkid.c
+++ b/toys/other/blkid.c
@@ -5,19 +5,20 @@
  * See ftp://ftp.kernel.org/pub/linux/utils/util-linux/v2.24/libblkid-docs/api-index-full.html
  * TODO: -U and -L should require arguments
 
-USE_BLKID(NEWTOY(blkid, "ULs*[!LU]", TOYFLAG_BIN))
+USE_BLKID(NEWTOY(blkid, "ULo:s*[!LU]", TOYFLAG_BIN))
 USE_FSTYPE(NEWTOY(fstype, "<1", TOYFLAG_BIN))
 
 config BLKID
   bool "blkid"
   default y
   help
-    usage: blkid [-s TAG] [-UL] DEV...
+    usage: blkid [-o TYPE] [-s TAG] [-UL] DEV...
 
     Print type, label and UUID of filesystem on a block device or image.
 
     -U	Show UUID only (or device with that UUID)
     -L	Show LABEL only (or device with that LABEL)
+    -o TYPE	Output format (full, value, export)
     -s TAG	Only show matching tags (default all)
 
 config FSTYPE
@@ -34,6 +35,7 @@
 
 GLOBALS(
   struct arg_list *s;
+  char *o;
 )
 
 struct fstype {
@@ -52,6 +54,7 @@
   {"btrfs", 0x4D5F53665248425FULL, 8, 65600, 65803, 256, 65819},
   {"cramfs", 0x28cd3d45, 4, 0, 0, 16, 48},
   {"f2fs", 0xF2F52010, 4, 1024, 1132, 512, 0x47c},
+  {"iso9660", 0x444301, 3, 0x8000, 0x832d, 32, 0x8028},
   {"jfs", 0x3153464a, 4, 32768, 32920, 16, 32904},
   {"nilfs", 0x3434, 2, 1030, 1176, 80, 1192},
   {"reiserfs", 0x724573496552ULL, 6, 8244, 8276, 16, 8292},
@@ -64,6 +67,19 @@
   {"vfat", 0x31544146, 4, 54, 39, 11, 43}     // fat1
 };
 
+static void escape(char *str, int force)
+{
+  if (!force && str[strcspn(str, "\" \\\n\t$<>|&;`'~()!#?")]) force++;
+  if (!force) return xputsn(str);
+
+  putchar('"');
+  while (*str) {
+    if (strchr("\" \\", *str)) putchar('\\');
+    putchar(*str++);
+  }
+  putchar('"');
+}
+
 static void show_tag(char *key, char *value)
 {
   int show = 0;
@@ -73,7 +89,13 @@
     for (al = TT.s; al; al = al->next) if (!strcmp(key, al->arg)) show = 1;
   } else show = 1;
 
-  if (show && *value) printf(" %s=\"%s\"", key, value);
+  if (!show || !*value) return;
+  if (!strcasecmp(TT.o, "full") || !strcasecmp(TT.o, "export")) {
+    printf(" %s="+!(*TT.o=='f'), key);
+    escape(value, *TT.o=='f');
+    if (*TT.o=='e') xputc('\n');
+  } else if (!strcasecmp(TT.o, "value")) xputs(value);
+  else error_exit("bad -o %s", TT.o);
 }
 
 static void flagshow(char *s, char *name)
@@ -137,13 +159,16 @@
   }
 
   // output for blkid
-  if (!FLAG(L) && !FLAG(U)) printf("%s:",name);
+  if (!FLAG(L) && !FLAG(U)) {
+    if (!TT.o || !strcasecmp(TT.o, "full")) printf("%s:", name);
+    else if (!strcasecmp(TT.o, "export")) show_tag("DEVNAME", name);
+  }
 
   len = fstypes[i].label_len;
   if (!FLAG(U) && len) {
     s = toybuf+fstypes[i].label_off-off;
-    if (!strcmp(type, "vfat")) {
-      show_tag("SEC_TYPE", "msdos");
+    if (!strcmp(type, "vfat") || !strcmp(type, "iso9660")) {
+      if (*type=='v') show_tag("SEC_TYPE", "msdos");
       while (len && s[len-1]==' ') len--;
       if (strstart(&s, "NO NAME")) len=0;
     }
@@ -174,6 +199,15 @@
     } else if (!strcmp(type, "vfat")) {
         s += sprintf(s, "%02X%02X-%02X%02X", toybuf[uoff+3], toybuf[uoff+2],
                      toybuf[uoff+1], toybuf[uoff]);
+    } else if (!strcmp(type, "iso9660")) {
+        s += sprintf(s, "%c%c%c%c-", toybuf[uoff], toybuf[uoff+1],
+                     toybuf[uoff+2], toybuf[uoff+3]);
+        s += sprintf(s, "%c%c-", toybuf[uoff+4], toybuf[uoff+5]);
+        s += sprintf(s, "%c%c-", toybuf[uoff+6], toybuf[uoff+7]);
+        s += sprintf(s, "%c%c-", toybuf[uoff+8], toybuf[uoff+9]);
+        s += sprintf(s, "%c%c-", toybuf[uoff+10], toybuf[uoff+11]);
+        s += sprintf(s, "%c%c-", toybuf[uoff+12], toybuf[uoff+13]);
+        s += sprintf(s, "%c%c", toybuf[uoff+14], toybuf[uoff+15]);
     } else {
       for (j = 0; j < 16; j++)
         s += sprintf(s, "-%02x"+!(0x550 & (1<<j)), toybuf[uoff+j]);
@@ -189,11 +223,13 @@
   if (FLAG(U) || FLAG(L)) return;
 
   show_tag("TYPE", type);
-  xputc('\n');
+  if (!strcasecmp(TT.o, "full")) xputc('\n');
 }
 
 void blkid_main(void)
 {
+  if (!TT.o) TT.o = "full";
+
   if (*toys.optargs && !FLAG(L) && !FLAG(U)) loopfiles(toys.optargs, do_blkid);
   else {
     unsigned int ma, mi, sz, fd;
diff --git a/toys/other/devmem.c b/toys/other/devmem.c
index 920d856..9c4dd87 100644
--- a/toys/other/devmem.c
+++ b/toys/other/devmem.c
@@ -2,7 +2,7 @@
  *
  * Copyright 2019 The Android Open Source Project
 
-USE_DEVMEM(NEWTOY(devmem, "<1>3", TOYFLAG_USR|TOYFLAG_BIN))
+USE_DEVMEM(NEWTOY(devmem, "<1>3", TOYFLAG_USR|TOYFLAG_SBIN))
 
 config DEVMEM
   bool "devmem"
diff --git a/toys/other/factor.c b/toys/other/factor.c
index 47e1267..4e893a0 100644
--- a/toys/other/factor.c
+++ b/toys/other/factor.c
@@ -3,8 +3,10 @@
  * Copyright 2014 Rob Landley <rob@landley.net>
  *
  * See https://man7.org/linux/man-pages/man1/factor.1.html
+ *
+ * -h and -x options come from https://man.netbsd.org/factor.6
 
-USE_FACTOR(NEWTOY(factor, 0, TOYFLAG_USR|TOYFLAG_BIN))
+USE_FACTOR(NEWTOY(factor, "?hx", TOYFLAG_USR|TOYFLAG_BIN))
 
 config FACTOR
   bool "factor"
@@ -13,17 +15,22 @@
     usage: factor NUMBER...
 
     Factor integers.
+
+    -h	Human readable: show repeated factors as x^n
+    -x	Hexadecimal output
 */
 
+#define FOR_factor
 #include "toys.h"
 
 static void factor(char *s)
 {
   unsigned long long l, ll, lll;
+  char *pat1 = FLAG(x) ? " %llx" : " %llu", *pat2 = FLAG(x) ? "^%x" : "^%u";
 
   for (;;) {
     char *err = s;
-    int dash = 0;
+    int dash = 0, ii;
 
     while(isspace(*s)) s++;
     if (*s=='-') dash = *s++;
@@ -37,34 +44,25 @@
       continue;
     }
 
-    printf("-%llu:"+!dash, l);
+    if (dash) xputc('-');
+    printf(pat1+1, l);
+    xputc(':');
 
     // Negative numbers have -1 as a factor
     if (dash) printf(" -1");
 
-    // Nothing below 4 has factors
-    if (l < 4) {
-      printf(" %llu\n", l);
-      continue;
-    }
-
-    // Special case factors of 2
-    while (l && !(l&1)) {
-      printf(" 2");
-      l >>= 1;
-    }
-
-    // test odd numbers until square is > remainder or integer wrap.
-    for (ll = 3;; ll += 2) {
+    // test 2 and odd numbers until square is > remainder or integer wrap.
+    for (ll = 2;; ll += 1+(ll!=2)) {
       lll = ll*ll;
       if (lll>l || lll<ll) {
-        if (l>1) printf(" %llu", l);
+        if (l>1 || ll==2) printf(pat1, l);
         break;
       }
-      while (!(l%ll)) {
-        printf(" %llu", ll);
+      for (ii = 0; !(l%ll); ii++) {
+        if (!ii || !FLAG(h)) printf(pat1, ll);
         l /= ll;
       }
+      if (ii>1 && FLAG(h)) printf(pat2, ii);
     }
     xputc('\n');
   }
diff --git a/toys/other/fmt.c b/toys/other/fmt.c
index a4460ec..744d67a 100644
--- a/toys/other/fmt.c
+++ b/toys/other/fmt.c
@@ -27,7 +27,7 @@
 #include "toys.h"
 
 GLOBALS(
-  int width;
+  long width;
 
   int level, pos;
 )
diff --git a/toys/other/fsfreeze.c b/toys/other/fsfreeze.c
index b494ce9..ee7bd53 100644
--- a/toys/other/fsfreeze.c
+++ b/toys/other/fsfreeze.c
@@ -7,7 +7,6 @@
 config FSFREEZE
   bool "fsfreeze"
   default y
-  depends on TOYBOX_FIFREEZE
   help
     usage: fsfreeze {-f | -u} MOUNTPOINT
 
@@ -26,6 +25,6 @@
   int fd = xopenro(*toys.optargs); 
   long p = 1;
 
-  xioctl(fd, (toys.optflags & FLAG_f) ? FIFREEZE : FITHAW, &p);
+  xioctl(fd, FLAG(f) ? FIFREEZE : FITHAW, &p);
   xclose(fd);
 }
diff --git a/toys/other/gpiod.c b/toys/other/gpiod.c
index cc3ce64..14fab5d 100644
--- a/toys/other/gpiod.c
+++ b/toys/other/gpiod.c
@@ -5,9 +5,9 @@
  * TODO: gpiomon
 
 USE_GPIODETECT(NEWTOY(gpiodetect, ">0", TOYFLAG_USR|TOYFLAG_BIN))
-USE_GPIOFIND(NEWTOY(gpioinfo, 0, TOYFLAG_USR|TOYFLAG_BIN))
+USE_GPIOINFO(NEWTOY(gpioinfo, 0, TOYFLAG_USR|TOYFLAG_BIN))
 USE_GPIOGET(NEWTOY(gpioget, "<2l", TOYFLAG_USR|TOYFLAG_BIN))
-USE_GPIOINFO(NEWTOY(gpiofind, "<1>1", TOYFLAG_USR|TOYFLAG_BIN))
+USE_GPIOFIND(NEWTOY(gpiofind, "<1>1", TOYFLAG_USR|TOYFLAG_BIN))
 USE_GPIOSET(NEWTOY(gpioset, "<2l", TOYFLAG_USR|TOYFLAG_BIN))
 
 config GPIODETECT
@@ -100,7 +100,7 @@
 static void foreach_chip(void (*cb)(char *name))
 {
   struct double_list **sorted;
-  int i = 0;
+  int i;
 
   dirtree_flagread("/dev", DIRTREE_SHUTUP, collect_chips);
   if (!TT.chips) return;
@@ -210,6 +210,7 @@
 #define FOR_gpioget
 #include "generated/flags.h"
 
+// TODO: half the get/set plumbing same here, maybe collate?
 void gpioget_main(void)
 {
   struct gpiohandle_request req = { .flags = GPIOHANDLE_REQUEST_INPUT };
diff --git a/toys/other/help.c b/toys/other/help.c
index 1cdbe7e..18fbed0 100644
--- a/toys/other/help.c
+++ b/toys/other/help.c
@@ -30,47 +30,51 @@
     xprintf("<a name=\"%s\"><h1>%s</h1><blockquote><pre>\n", t->name, t->name);
 
   toys.which = t;
-  show_help(stdout, !FLAG(u)+(!!toys.argv[1]<<1));
+  show_help(stdout, HELP_USAGE*FLAG(u) + (HELP_SEE|HELP_HTML)*FLAG(h));
 
   if (FLAG(h)) xprintf("</blockquote></pre>\n");
 }
 
-// Simple help is just toys.which = toy_find("name"); show_help(stdout, 1);
+// Simple help is just toys.which = toy_find("name"); show_help(stdout, 0);
 // but iterating through html output and all commands is a bit more
 
 void help_main(void)
 {
-  int i;
+  long i;
 
   // If called with no arguments as a builtin from the shell, show all builtins
   if (toys.rebound && !*toys.optargs && !toys.optflags) {
     for (i = 0; i < toys.toycount; i++) {
       if (!(toy_list[i].flags&(TOYFLAG_NOFORK|TOYFLAG_MAYFORK))) continue;
       toys.which = toy_list+i;
-      show_help(stdout, FLAG(u));
+      show_help(stdout, HELP_SEE|HELP_USAGE*!toys.optflags);
     }
     return;
   }
 
   if (!FLAG(a)) {
-    struct toy_list *t = toys.which;
+    struct toy_list *t = toys.which, *tt;
 
-    if (*toys.optargs && !(t = toy_find(*toys.optargs)))
-      error_exit("Unknown command '%s'", *toys.optargs);
-    do_help(t);
-    return;
+    // Zero which to include "toybox" in search, put it back for error msg
+    toys.which = 0;
+    tt = *toys.optargs ? toy_find(*toys.optargs) : t;
+    toys.which = t;
+
+    if (tt) return do_help(tt);
+    else error_exit("Unknown command '%s'", *toys.optargs);
   }
 
   if (FLAG(h)) {
     sprintf(toybuf, "Toybox %s command help", toybox_version);
     xprintf("<html>\n<title>%s</title>\n<body>\n<h1>%s</h1><hr /><p>",
             toybuf, toybuf);
-    for (i=0; i < toys.toycount; i++)
-      xprintf("<a href=\"#%s\">%s</a> \n", toy_list[i].name, toy_list[i].name);
+    for (i = 0; i<toys.toycount; i++) if (toy_list[i].flags)
+      xprintf("<a href=\"#%s\">%s</a>\n", toy_list[i].name,toy_list[i].name);
     xprintf("</p>\n");
   }
 
   for (i = 0; i < toys.toycount; i++) {
+    if (!toy_list[i].flags) continue;
     if (FLAG(h)) xprintf("<hr>\n<pre>\n");
     else if (!FLAG(u)) {
       memset(toybuf, '-', 78);
diff --git a/toys/other/hexedit.c b/toys/other/hexedit.c
index d340205..4550dc3 100644
--- a/toys/other/hexedit.c
+++ b/toys/other/hexedit.c
@@ -181,7 +181,7 @@
   size_t len = strlen(TT.search);
 
   for (; pos >= 0; pos--) {
-    if (!memcmp(TT.data+pos, TT.search, len)) {
+    if (!smemcmp(TT.data+pos, TT.search, len)) {
       TT.pos = pos;
       return;
     }
diff --git a/toys/other/hwclock.c b/toys/other/hwclock.c
index 541c70a..eaec842 100644
--- a/toys/other/hwclock.c
+++ b/toys/other/hwclock.c
@@ -47,11 +47,11 @@
     if (!TT.f) TT.f = "/dev/rtc0";
     fd = xopen(TT.f, O_WRONLY*FLAG(w));
 
-    // Get current time in seconds from rtc device. todo: get subsecond time
+    // Get current time in seconds from rtc device. TODO: get subsecond time
     if (!FLAG(w)) {
       xioctl(fd, RTC_RD_TIME, &tm);
       timeval.tv_sec = xmktime(&tm, utc);
-      timeval.tv_usec = 0; // todo: fixit
+      timeval.tv_usec = 0; // TODO: fixit
     }
   }
 
@@ -64,7 +64,7 @@
   if (FLAG(w)) {
     /* The value of tm_isdst is positive if daylight saving time is in effect,
      * zero if it is not and negative if the information is not available. 
-     * todo: so why isn't this negative...? */
+     * TODO: so why isn't this negative...? */
     tm.tm_isdst = 0;
     xioctl(fd, RTC_SET_TIME, &tm);
   } else if (FLAG(s)) {
diff --git a/toys/other/i2ctools.c b/toys/other/i2ctools.c
index bce160d..ad296ad 100644
--- a/toys/other/i2ctools.c
+++ b/toys/other/i2ctools.c
@@ -10,11 +10,13 @@
  * TODO: i2cdump non-byte modes, -r FIRST-LAST?
  * TODO: i2cget non-byte modes? default to current read address?
  * TODO: i2cset -r? -m MASK? c/s modes, p mode modifier?
+ * TODO: I2C_M_TEN bit addressing (-t, larger range in probe...)
 
-USE_I2CDETECT(NEWTOY(i2cdetect, ">3aFlqry[!qr]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_I2CDUMP(NEWTOY(i2cdump, "<2>2fy", TOYFLAG_USR|TOYFLAG_BIN))
-USE_I2CGET(NEWTOY(i2cget, "<3>3fy", TOYFLAG_USR|TOYFLAG_BIN))
-USE_I2CSET(NEWTOY(i2cset, "<4fy", TOYFLAG_USR|TOYFLAG_BIN))
+// note: confirm() needs "y" to be in same place for all commands
+USE_I2CDETECT(NEWTOY(i2cdetect, ">3aFlqry[!qr]", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_I2CDUMP(NEWTOY(i2cdump, "<2>2fy", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_I2CGET(NEWTOY(i2cget, "<2>3fy", TOYFLAG_USR|TOYFLAG_SBIN))
+USE_I2CSET(NEWTOY(i2cset, "<4fy", TOYFLAG_USR|TOYFLAG_SBIN))
 
 config I2CDETECT
   bool "i2cdetect"
@@ -31,7 +33,7 @@
     -l	List available buses
     -q	Probe with SMBus Quick Write (default)
     -r	Probe with SMBus Read Byte
-    -y	Answer "yes" to confirmation prompts (for script use)
+    -y	Skip confirmation prompts (yes to all)
 
 config I2CDUMP
   bool "i2cdump"
@@ -42,18 +44,18 @@
     Dump i2c registers.
 
     -f	Force access to busy devices
-    -y	Answer "yes" to confirmation prompts (for script use)
+    -y	Skip confirmation prompts (yes to all)
 
 config I2CGET
   bool "i2cget"
   default y
   help
-    usage: i2cget [-fy] BUS CHIP ADDR
+    usage: i2cget [-fy] BUS CHIP [ADDR]
 
     Read an i2c register.
 
     -f	Force access to busy devices
-    -y	Answer "yes" to confirmation prompts (for script use)
+    -y	Skip confirmation prompts (yes to all)
 
 config I2CSET
   bool "i2cset"
@@ -64,10 +66,11 @@
     Write an i2c register. MODE is b for byte, w for 16-bit word, i for I2C block.
 
     -f	Force access to busy devices
-    -y	Answer "yes" to confirmation prompts (for script use)
+    -y	Skip confirmation prompts (yes to all)
 */
 
 #define FOR_i2cdetect
+#define FORCE_FLAGS
 #define TT this.i2ctools
 #include "toys.h"
 
@@ -86,13 +89,13 @@
   if (!yesno(1)) error_exit("Exiting");
 }
 
-static int i2c_open(int bus, int slave, int chip)
+static int i2c_open(int bus, int slave, long chip)
 {
   int fd;
 
-  snprintf(toybuf, sizeof(toybuf), "/dev/i2c-%d", bus);
+  sprintf(toybuf, "/dev/i2c-%d", bus);
   fd = xopen(toybuf, O_RDONLY);
-  if (slave) xioctl(fd, slave, (void *)(long)chip);
+  if (slave) xioctl(fd, slave, (void *)chip);
   return fd;
 }
 
@@ -103,10 +106,11 @@
 
   xioctl(fd, I2C_FUNCS, &result);
   close(fd);
+
   return result;
 }
 
-static int i2c_read_byte(int fd, int addr, int *byte)
+static int i2c_read_byte(int fd, int addr, char *byte)
 {
   union i2c_smbus_data data;
   struct i2c_smbus_ioctl_data ioctl_data = { .read_write = I2C_SMBUS_READ,
@@ -115,42 +119,31 @@
   memset(&data, 0, sizeof(data));
   if (ioctl(fd, I2C_SMBUS, &ioctl_data)==-1) return -1;
   *byte = data.byte;
+
   return 0;
 }
 
 static int i2c_quick_write(int fd, int addr)
 {
   struct i2c_smbus_ioctl_data ioctl_data = { .read_write = I2C_SMBUS_QUICK,
-    .size = 0, .command = addr };
+    .command = addr };
 
   return ioctl(fd, I2C_SMBUS, &ioctl_data);
 }
 
 static void i2cdetect_dash_F(int bus)
 {
-  struct { int mask; const char *name; } funcs[] = {
-    {I2C_FUNC_I2C, "I2C"},
-    {I2C_FUNC_SMBUS_QUICK, "SMBus Quick Command"},
-    {I2C_FUNC_SMBUS_WRITE_BYTE, "SMBus Send Byte"},
-    {I2C_FUNC_SMBUS_READ_BYTE, "SMBus Receive Byte"},
-    {I2C_FUNC_SMBUS_WRITE_BYTE_DATA, "SMBus Write Byte"},
-    {I2C_FUNC_SMBUS_READ_BYTE_DATA, "SMBus Read Byte"},
-    {I2C_FUNC_SMBUS_WRITE_WORD_DATA, "SMBus Write Word"},
-    {I2C_FUNC_SMBUS_READ_WORD_DATA, "SMBus Read Word"},
-    {I2C_FUNC_SMBUS_PROC_CALL, "SMBus Process Call"},
-    {I2C_FUNC_SMBUS_WRITE_BLOCK_DATA, "SMBus Write Block"},
-    {I2C_FUNC_SMBUS_READ_BLOCK_DATA, "SMBus Read Block"},
-    {I2C_FUNC_SMBUS_BLOCK_PROC_CALL, "SMBus Block Process Call"},
-    {I2C_FUNC_SMBUS_PEC, "SMBus PEC"},
-    {I2C_FUNC_SMBUS_WRITE_I2C_BLOCK, "I2C Write Block"},
-    {I2C_FUNC_SMBUS_READ_I2C_BLOCK, "I2C Read Block"},
-  };
-  unsigned long sup = i2c_get_funcs(bus);
-  int i;
+  char *funcs[] = {
+    "I2C", "10 bit", 0, "SMBus PEC", 0, 0, "SMBus Block Process Call",
+    "SMBus Quick Command", "SMBus Receive Byte", "SMBus Send Byte",
+    "SMBus Read Byte", "SMBus Write Byte", "SMBus Read Word",
+    "SMBus Write Word", "SMBus Process Call", "SMBus Read Block",
+    "SMBus Write Block", "I2C Read Block", "I2C Write Block" };
+  unsigned sup = i2c_get_funcs(bus), i;
 
   printf("Functionalities implemented by %s:\n", toybuf);
-  for (i = 0; i < ARRAY_LEN(funcs); ++i)
-    printf("%-32s %s\n", funcs[i].name, (sup & funcs[i].mask) ? "yes" : "no");
+  for (i = 0; i<ARRAY_LEN(funcs); i++)
+    if (funcs[i]) printf("%-32s %s\n", funcs[i], (sup&(1<<i)) ? "yes" : "no");
 }
 
 static int i2cdetect_dash_l(struct dirtree *node)
@@ -186,9 +179,10 @@
     dirtree_flagread("/sys/class/i2c-dev", DIRTREE_SHUTUP, i2cdetect_dash_l);
   } else if (FLAG(F)) {
     if (toys.optc != 1) error_exit("-F BUS");
-    i2cdetect_dash_F(atolx_range(*toys.optargs, 0, INT_MAX));
+    i2cdetect_dash_F(atolx_range(*toys.optargs, 0, 0x3f));
   } else {
-    int bus, first = 0x03, last = 0x77, fd, row, addr, byte;
+    int bus, first = 0x03, last = 0x77, fd, row, addr;
+    char byte;
 
     if (FLAG(a)) {
       first = 0x00;
@@ -196,7 +190,7 @@
     }
 
     if (toys.optc!=1 && toys.optc!=3) help_exit("Needs 1 or 3 arguments");
-    bus = atolx_range(*toys.optargs, 0, INT_MAX);
+    bus = atolx_range(*toys.optargs, 0, 0x3f);
     if (toys.optc==3) {
       first = atolx_range(toys.optargs[1], 0, 0x7f);
       last = atolx_range(toys.optargs[2], 0, 0x7f);
@@ -207,22 +201,24 @@
 
     fd = i2c_open(bus, 0, 0);
     printf("     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f\n");
-    for (row = 0; row <= 0x70; row += 16) {
+    for (row = 0; row < 0x80; row += 16) {
       xprintf("%02x:", row & 0xf0);
       for (addr = row; addr<row+16; ++addr) {
-        if (addr<first || addr>last) printf("   ");
-        else {
-          if (ioctl(fd, I2C_SLAVE, addr) == -1) {
-            if (errno == EBUSY) {
-              xprintf(" UU");
-              continue;
-            }
-            perror_exit("ioctl(I2C_SLAVE)");
-          }
-          if ((FLAG(r) ? i2c_read_byte(fd, addr, &byte)
-                       : i2c_quick_write(fd, addr)) == -1) xprintf(" --");
-          else xprintf(" %02x", addr);
+        if (addr<first || addr>last) {
+          printf("   ");
+
+          continue;
         }
+        if (ioctl(fd, I2C_SLAVE, addr) == -1) {
+          if (errno == EBUSY) {
+            xprintf(" UU");
+            continue;
+          }
+          perror_exit("ioctl(I2C_SLAVE)");
+        }
+        if ((FLAG(r) ? i2c_read_byte(fd, addr, &byte)
+                     : i2c_quick_write(fd, addr)) == -1) xprintf(" --");
+        else xprintf(" %02x", addr);
       }
       putchar('\n');
     }
@@ -235,15 +231,15 @@
 
 void i2cdump_main(void)
 {
-  int bus = atolx_range(toys.optargs[0], 0, INT_MAX);
-  int chip = atolx_range(toys.optargs[1], 0, 0x7f);
-  int fd, row, addr, byte;
+  int fd, row, addr, bus = atolx_range(toys.optargs[0], 0, 0x3f),
+      chip = atolx_range(toys.optargs[1], 0, 0x7f);
+  char byte;
 
   confirm("Dump chip 0x%02x on bus %d?", chip, bus);
 
   fd = i2c_open(bus, FLAG(f) ? I2C_SLAVE_FORCE : I2C_SLAVE, chip);
   printf("     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef\n");
-  for (row = 0; row<=0xf0; row += 16) {
+  for (row = 0; row<0x100; row += 16) {
     xprintf("%02x:", row & 0xf0);
     for (addr = row; addr<row+16; ++addr) {
       if (!i2c_read_byte(fd, addr, &byte)) printf(" %02x", byte);
@@ -251,7 +247,7 @@
         printf(" XX");
         byte = 'X';
       }
-      toybuf[addr-row] = isprint(byte) ? byte : (byte ? '?' : '.');
+      toybuf[addr-row] = isprint(byte) ? byte : byte ? '?' : '.';
     }
     printf("    %16.16s\n", toybuf);
   }
@@ -263,15 +259,18 @@
 
 void i2cget_main(void)
 {
-  int bus = atolx_range(toys.optargs[0], 0, INT_MAX);
-  int chip = atolx_range(toys.optargs[1], 0, 0x7f);
-  int addr = atolx_range(toys.optargs[2], 0, 0xff);
-  int fd, byte;
+  int fd, bus = atolx_range(toys.optargs[0], 0, 0x3f),
+      chip = atolx_range(toys.optargs[1], 0, 0x7f),
+      addr = (toys.optc == 3) ? atolx_range(toys.optargs[2], 0, 0xff) : -1;
+  char byte;
 
   confirm("Read register 0x%02x from chip 0x%02x on bus %d?", addr, chip, bus);
 
   fd = i2c_open(bus, FLAG(f) ? I2C_SLAVE_FORCE : I2C_SLAVE, chip);
-  if (i2c_read_byte(fd, addr, &byte)==-1) perror_exit("i2c_read_byte");
+  if (toys.optc == 3) {
+    if (i2c_read_byte(fd, addr, &byte)==-1) perror_exit("i2c_read_byte");
+  } else if (read(fd, &byte, 1) != 1) perror_exit("i2c_read");
+
   printf("0x%02x\n", byte);
   close(fd);
 }
@@ -281,11 +280,10 @@
 
 void i2cset_main(void)
 {
-  int bus = atolx_range(toys.optargs[0], 0, INT_MAX);
-  int chip = atolx_range(toys.optargs[1], 0, 0x7f);
-  int addr = atolx_range(toys.optargs[2], 0, 0xff);
+  int fd, i, bus = atolx_range(toys.optargs[0], 0, 0x3f),
+      chip = atolx_range(toys.optargs[1], 0, 0x7f),
+      addr = atolx_range(toys.optargs[2], 0, 0xff);
   char *mode = toys.optargs[toys.optc-1];
-  int fd, i;
   struct i2c_smbus_ioctl_data ioctl_data;
   union i2c_smbus_data data;
 
@@ -300,13 +298,14 @@
   } else if (*mode=='i' && toys.optc>=5) {
     if (toys.optc-4>I2C_SMBUS_BLOCK_MAX) error_exit("too much data");
     ioctl_data.size = I2C_SMBUS_I2C_BLOCK_DATA;
-    for (i = 0; i<toys.optc-4; ++i)
-      data.block[i+1] = atolx_range(toys.optargs[3+i], 0, 0xff);
     data.block[0] = toys.optc-4;
+    for (i = 0; i<toys.optc-4; i++)
+      data.block[i+1] = atolx_range(toys.optargs[3+i], 0, 0xff);
   } else help_exit("syntax error");
 
   confirm("Write register 0x%02x from chip 0x%02x on bus %d?", addr, chip, bus);
 
+  // We open the device read-only and the write command works?
   fd = i2c_open(bus, FLAG(f) ? I2C_SLAVE_FORCE : I2C_SLAVE, chip);
   ioctl_data.read_write = I2C_SMBUS_WRITE;
   ioctl_data.command = addr;
diff --git a/toys/other/login.c b/toys/other/login.c
index 5214b93..62c1293 100644
--- a/toys/other/login.c
+++ b/toys/other/login.c
@@ -10,7 +10,6 @@
 config LOGIN
   bool "login"
   default y
-  depends on TOYBOX_SHADOW
   help
     usage: login [-p] [-h host] [-f USERNAME] [USERNAME]
 
@@ -38,7 +37,7 @@
 
 void login_main(void)
 {
-  int hh = FLAG(h), count, tty = tty_fd();
+  int count, tty = tty_fd();
   char *username, *pass = 0, *ss;
   struct passwd *pwd = 0;
 
@@ -79,7 +78,12 @@
       if (*(pass = pwd->pw_passwd) == 'x') {
         struct spwd *spwd = getspnam (username);
 
-        if (spwd) pass = spwd->sp_pwdp;
+        if (spwd) {
+          pass = spwd->sp_pwdp;
+
+          // empty shadow password
+          if (pass && !*pass) break;
+        }
       }
     } else if (TT.f) error_exit("bad -f '%s'", TT.f);
 
@@ -92,8 +96,8 @@
       if (x) break;
     }
 
-    syslog(LOG_WARNING, "invalid password for '%s' on %s %s%s", pwd->pw_name,
-      ttyname(tty), hh ? "from " : "", hh ? TT.h : "");
+    syslog(LOG_WARNING, "invalid password for '%s' on %s %s%s", username,
+      ttyname(tty), TT.h ? "from " : "", TT.h ? : "");
 
     sleep(3);
     puts("Login incorrect");
@@ -125,7 +129,7 @@
   if ((ss = readfile("/etc/motd", 0, 0))) puts(ss);
 
   syslog(LOG_INFO, "%s logged in on %s %s %s", pwd->pw_name,
-    ttyname(tty), hh ? "from" : "", hh ? TT.h : "");
+    ttyname(tty), TT.h ? "from" : "", TT.h ? : "");
 
   // not using xexec(), login calls absolute path from filesystem so must exec()
   execl(pwd->pw_shell, xmprintf("-%s", pwd->pw_shell), (char *)0);
diff --git a/toys/other/losetup.c b/toys/other/losetup.c
index ce84c1e..0973273 100644
--- a/toys/other/losetup.c
+++ b/toys/other/losetup.c
@@ -71,6 +71,16 @@
       }
       close(cfd);
     }
+    if (CFG_TOYBOX_ON_ANDROID && device) {
+      // ANDROID SPECIFIC: /dev is not devtmpfs, instead an userspace daemon
+      // ueventd is responsible for creating the loop devices under /dev.
+      // Wait for the uevent to be processed to avoid race.
+      long long timeout = millitime() + 5000;
+      do {
+        if (!access(device, F_OK) || errno != ENOENT) break;
+        msleep(20);
+      } while (millitime() < timeout);
+    }
   }
 
   if (device) lfd = open(device, TT.openflags);
diff --git a/toys/other/lsattr.c b/toys/other/lsattr.c
index 31d7f43..5be8301 100644
--- a/toys/other/lsattr.c
+++ b/toys/other/lsattr.c
@@ -198,10 +198,11 @@
 // Get directory information.
 static int retell_dir(struct dirtree *root)
 {
-  char *fpath = NULL;
+  char *fpath = 0;
 
   if (root->again) {
     xputc('\n');
+
     return 0;
   }
   if (S_ISDIR(root->st.st_mode) && !root->parent)
@@ -209,7 +210,7 @@
 
   fpath = dirtree_path(root, NULL);
   //Special case: with '-a' option and '.'/'..' also included in printing list.
-  if ((root->name[0] != '.') || FLAG(a)) {
+  if (*root->name != '.' || FLAG(a)) {
     print_file_attr(fpath);
     if (S_ISDIR(root->st.st_mode) && FLAG(R) && dirtree_notdotdot(root)) {
       xprintf("\n%s:\n", fpath);
@@ -218,6 +219,7 @@
     }
   }
   free(fpath);
+
   return 0;
 }
 
diff --git a/toys/other/lsusb.c b/toys/other/lsusb.c
index 836c4f6..600858b 100644
--- a/toys/other/lsusb.c
+++ b/toys/other/lsusb.c
@@ -4,7 +4,7 @@
  * Copyright 2013 Isaac Dunham <ibid.ag@gmail.com>
 
 USE_LSUSB(NEWTOY(lsusb, "i:", TOYFLAG_USR|TOYFLAG_BIN))
-USE_LSPCI(NEWTOY(lspci, "emkn@i:", TOYFLAG_USR|TOYFLAG_BIN))
+USE_LSPCI(NEWTOY(lspci, "emkn@x@i:", TOYFLAG_USR|TOYFLAG_BIN))
 
 config LSPCI
   bool "lspci"
@@ -14,11 +14,12 @@
 
     List PCI devices.
 
-    -e  Extended (6 digit) class
-    -i  ID database (default /etc/pci.ids[.gz])
-    -k  Show kernel driver
-    -m  Machine readable
-    -n  Numeric output (-nn for both)
+    -e	Extended (6 digit) class
+    -i	ID database (default /etc/pci.ids[.gz])
+    -k	Show kernel driver
+    -m	Machine readable
+    -n	Numeric output (-nn for both)
+    -x	Hex dump of config space (64 bytes; -xxx for 256, -xxxx for 4096)
 
 config LSUSB
   bool "lsusb"
@@ -36,7 +37,7 @@
 
 GLOBALS(
   char *i;
-  long n;
+  long x, n;
 
   void *ids, *class;
   int count;
@@ -57,7 +58,7 @@
 // note that %s is omitted (because pointer is into toybuf, avoiding copy).
 static int scan_uevent(struct dirtree *new, int len, struct scanloop *sl)
 {
-  int ii, count = 0;
+  int ii, saw = 0;
   off_t flen = sizeof(toybuf);
   char *ss, *yy;
 
@@ -74,18 +75,18 @@
     // Try each pattern
     for (ii = 0; ii<len; ii++) {
       if (strchr(sl[ii].pattern, '%')) {
-        if (2-!sl[ii].d2==sscanf(ss, sl[ii].pattern, sl[ii].d1, sl[ii].d2))
-          break;
-      } else if (strstart(&ss, sl[ii].pattern)) {
-        *(void **)sl[ii].d1 = ss;
-        break;
-      }
+        if (2-!sl[ii].d2!=sscanf(ss, sl[ii].pattern, sl[ii].d1, sl[ii].d2))
+          continue;
+      } else if (strstart(&ss, sl[ii].pattern)) *(void **)sl[ii].d1 = ss;
+      else continue;
+      saw |= 1<<ii;
+
+      break;
     }
-    if (ii!=len) count++;
     ss = yy;
   }
 
-  return count;
+  return saw;
 }
 
 static void get_names(struct dev_ids *ids, int id1, int id2,
@@ -109,18 +110,22 @@
 struct dev_ids *parse_dev_ids(char *name, struct dev_ids **and)
 {
   char *path = "/etc:/vendor:/usr/share/misc";
-  struct string_list *sl;
+  struct string_list *sl = 0;
   FILE *fp;
   char *s, *ss, *sss;
   struct dev_ids *ids = 0, *new;
-  int fd = -1, tick = 0;
+  int fd = -1;
 
   // Open compressed or uncompressed file
-  sprintf(toybuf, "%s.gz", name);
-  if ((sl = find_in_path(path, toybuf))) {
-    signal(SIGCHLD, SIG_IGN);
-    xpopen((char *[]){"zcat", sl->str, 0}, &fd, 1);
-  } else if ((sl = find_in_path(path, name))) fd = xopen(sl->str,O_RDONLY);
+  signal(SIGCHLD, SIG_IGN);
+  s = TT.i;
+  if (!s) {
+    sprintf(toybuf, "%s.gz", name);
+    if ((sl = find_in_path(path, toybuf)) || (sl = find_in_path(path, name)))
+      s = sl->str;
+  }
+  if (s && strend(s, ".gz")) xpopen((char *[]){"zcat", sl->str, 0}, &fd, 1);
+  else if (s) fd = xopen(s, O_RDONLY);
   llist_traverse(sl, free);
   if (fd == -1) return 0;
   
@@ -132,8 +137,7 @@
     if (strstart(&ss, "C ") && and) {
       *and = ids;
       and = 0;
-      tick++;
-    } 
+    }
     fd = estrtol(sss = ss, &ss, 16);
     if (ss>sss && *ss++==' ') {
       while (isspace(*ss)) ss++;
@@ -161,7 +165,7 @@
   char *n1, *n2;
 
   if (!new->parent) return DIRTREE_RECURSE;
-  if (3 == scan_uevent(new, 3, (struct scanloop[]){{"BUSNUM=%u", &busnum, 0},
+  if (7 == scan_uevent(new, 3, (struct scanloop[]){{"BUSNUM=%u", &busnum, 0},
     {"DEVNUM=%u", &devnum, 0}, {"PRODUCT=%x/%x", &pid, &vid}}))
   {
     get_names(TT.ids, pid, vid, &n1, &n2);
@@ -203,7 +207,7 @@
   }
 
   // Load uevent data, look up names in database
-  if (3 != scan_uevent(new, 3, (struct scanloop[]){{"DRIVER=", &driver, 0},
+  if (6>scan_uevent(new, 3, (struct scanloop[]){{"DRIVER=", &driver, 0},
     {"PCI_CLASS=%x", cvd, 0}, {"PCI_ID=%x:%x", cvd+1, cvd+2}})) return 0;
   get_names(TT.class, 255&(cvd[0]>>16), 255&(cvd[0]>>8), names, names);
   get_names(TT.ids, cvd[1], cvd[2], names+1, names+2);
@@ -222,10 +226,28 @@
       break;
     } else printf(" \"%s [%s]\"", names[ii], buf);
   }
-  printf(FLAG(m) ? " -r%02x" : " (rev %02x)", revision);
-  if (FLAG(k)) printf(FLAG(m) ? " \"%s\"" : " %s", driver);
+  if (revision) printf(FLAG(m) ? " -r%02x" : " (rev %02x)", revision);
+  if (FLAG(k) && driver) printf(FLAG(m) ? " \"%s\"" : " %s", driver);
   xputc('\n');
 
+  if (TT.x) {
+    FILE *fp;
+    int b, col = 0, max = (TT.x >= 4) ? 4096 : ((TT.x >= 3) ? 256 : 64);
+
+    // TODO: where does the "0000:" come from?
+    snprintf(toybuf, sizeof(toybuf), "/sys/bus/pci/devices/0000:%s/config",
+      new->name+5);
+    fp = xfopen(toybuf, "r");
+    while ((b = fgetc(fp)) != EOF) {
+      if ((col % 16) == 0) printf("%02x: ", col & 0xf0);
+      printf("%02x ", (b & 0xff));
+      if ((++col % 16) == 0) xputc('\n');
+      if (col == max) break;
+    }
+    xputc('\n');
+    fclose(fp);
+  }
+
   return 0;
 }
 
diff --git a/toys/other/mcookie.c b/toys/other/mcookie.c
index fb83f5e..813b74b 100644
--- a/toys/other/mcookie.c
+++ b/toys/other/mcookie.c
@@ -29,7 +29,7 @@
   long long *ll = (void *)toybuf;
 
   if (FLAG(V)) return (void)puts("mcookie from toybox");
-  xgetrandom(toybuf, 16, 0);
+  xgetrandom(toybuf, 16);
   if (FLAG(v)) fputs("Got 16 bytes from xgetrandom()\n", stderr);
   xprintf("%016llx%06llx\n", ll[0], ll[1]);
 }
diff --git a/toys/other/mkswap.c b/toys/other/mkswap.c
index 3106ea8..806e182 100644
--- a/toys/other/mkswap.c
+++ b/toys/other/mkswap.c
@@ -42,7 +42,7 @@
 
   if (CFG_TOYBOX_FREE) close(fd);
 
-  if (TT.L) sprintf(toybuf, ", LABEL=%s", label);
+  if (TT.L) sprintf(toybuf, ", LABEL=%.15s", TT.L);
   else *toybuf = 0;
   printf("Swapspace size: %luk%s, UUID=%s\n",
     pages*(unsigned long)(pagesize/1024),
diff --git a/toys/other/modinfo.c b/toys/other/modinfo.c
index 6c1e939..e1a64ba 100644
--- a/toys/other/modinfo.c
+++ b/toys/other/modinfo.c
@@ -44,6 +44,7 @@
   char *buf = 0, *end, *modinfo_tags[] = {
     "license", "author", "description", "firmware", "alias", "srcversion",
     "depends", "retpoline", "intree", "name", "vermagic", "parm", "parmtype",
+    "scmversion",
   };
 
   if (-1 != (fd = open(full_name, O_RDONLY))) {
diff --git a/toys/other/mountpoint.c b/toys/other/mountpoint.c
index a97c600..7985cbb 100644
--- a/toys/other/mountpoint.c
+++ b/toys/other/mountpoint.c
@@ -23,7 +23,7 @@
 
 static void die(char *gripe)
 {
-  if (!(toys.optflags & FLAG_q)) printf("%s: not a %s\n", *toys.optargs, gripe);
+  if (!FLAG(q)) printf("%s: not a %s\n", *toys.optargs, gripe);
 
   toys.exitval++;
   xexit();
@@ -33,34 +33,30 @@
 {
   struct stat st1, st2;
   char *arg = *toys.optargs;
-  int quiet = toys.optflags & FLAG_q;
 
-  if (lstat(arg, &st1)) perror_exit_raw(arg);
+  if (lstat(arg, &st1)) (FLAG(q) ? die : perror_exit_raw)(arg);
 
-  if (toys.optflags & FLAG_x) {
-    if (S_ISBLK(st1.st_mode)) {
-      if (!quiet)
-        printf("%u:%u\n", dev_major(st1.st_rdev), dev_minor(st1.st_rdev));
+  if (FLAG(x)) {
+    if (!S_ISBLK(st1.st_mode)) die("block device");
+    if (!FLAG(q))
+      printf("%u:%u\n", dev_major(st1.st_rdev), dev_minor(st1.st_rdev));
 
-      return;
-    }
-    die("block device");
+    return;
   }
 
-  // TODO: Ignore the fact a file can be a mountpoint for --bind mounts.
+  // TODO: a file can be a mountpoint for --bind mounts.
   if (!S_ISDIR(st1.st_mode)) die("directory");
 
   arg = xmprintf("%s/..", arg);
   xstat(arg, &st2);
-  if (CFG_TOYBOX_FREE) free(arg);
+  free(arg);
 
   // If the device is different, it's a mount point. If the device _and_
   // inode are the same, it's probably "/". This misses --bind mounts from
   // elsewhere in the same filesystem, but so does the other one and in the
   // absence of a spec I guess that's the expected behavior?
   toys.exitval = !(st1.st_dev != st2.st_dev || st1.st_ino == st2.st_ino);
-  if (toys.optflags & FLAG_d)
-    printf("%u:%u\n", dev_major(st1.st_dev), dev_minor(st1.st_dev));
-  else if (!quiet)
+  if (FLAG(d)) printf("%u:%u\n", dev_major(st1.st_dev), dev_minor(st1.st_dev));
+  else if (!FLAG(q))
     printf("%s is %sa mountpoint\n", *toys.optargs, toys.exitval ? "not " : "");
 }
diff --git a/toys/other/nbd_client.c b/toys/other/nbd_client.c
index ad3440a..caa7da6 100644
--- a/toys/other/nbd_client.c
+++ b/toys/other/nbd_client.c
@@ -7,28 +7,26 @@
 // This little dance is because a NEWTOY with - in the name tries to do
 // things like prototype "nbd-client_main" which isn't a valid symbol. So
 // we hide the underscore name and OLDTOY the name we want.
-USE_NBD_CLIENT(NEWTOY(nbd_client, "<3>3ns", 0))
+USE_NBD_CLIENT(NEWTOY(nbd_client, "<3>3b#<1>4294967295=4096ns", 0))
 USE_NBD_CLIENT(OLDTOY(nbd-client, nbd_client, TOYFLAG_USR|TOYFLAG_BIN))
 
 config NBD_CLIENT
   bool "nbd-client"
-  depends on TOYBOX_FORK
   default y
   help
-    usage: nbd-client [-ns] HOST PORT DEVICE
+    usage: nbd-client [-ns] [-b BLKSZ] HOST PORT DEVICE
 
-    -n	Do not fork into background
+    -b	Block size (default 4096)
+    -n	Do not daemonize
     -s	nbd swap support (lock server into memory)
 */
 
 /*  TODO:
-    usage: nbd-client [-sSpn] [-b BLKSZ] [-t SECS] [-N name] HOST PORT DEVICE
+    usage: nbd-client [-Sp] [-t SECS] [-N name] HOST PORT DEVICE
 
-    -b	block size
     -t	timeout in seconds
     -S	sdp
     -p	persist
-    -n	nofork
     -d	DEVICE
     -c	DEVICE
 */
@@ -37,78 +35,88 @@
 #include "toys.h"
 #include <linux/nbd.h>
 
+GLOBALS(
+  long b;
+
+  int nbd;
+)
+
+static void sig_cleanup(int catch)
+{
+  // Flush on the way out
+  ioctl(TT.nbd, NBD_CLEAR_QUE);
+  ioctl(TT.nbd, NBD_CLEAR_SOCK);
+  _exit(catch ? 128+catch : 0);
+}
+
 void nbd_client_main(void)
 {
-  int sock = -1, nbd, flags;
+  int sock = -1, flags, temp;
   unsigned long timeout = 0;
   char *host=toys.optargs[0], *port=toys.optargs[1], *device=toys.optargs[2];
-  uint64_t devsize;
+  unsigned long long devsize;
 
-  // Repeat until spanked
+  // Daemonize in a nommu-friendly way, but retain stderr
+  if (toys.stacktop && !FLAG(n)) {
+    dup2(2, 222);
+    xvdaemon();
+  }
+  dup2(222, 2);
+  close(222);
 
-  nbd = xopen(device, O_RDWR);
+  TT.nbd = xopen(device, O_RDWR);
+  xsignal(SIGINT, sig_cleanup);
+  xsignal(SIGTERM, sig_cleanup);
+
   for (;;) {
-    int temp;
-
     // Find and connect to server
-
     sock = xconnectany(xgetaddrinfo(host, port, AF_UNSPEC, SOCK_STREAM, 0, 0));
     temp = 1;
     setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &temp, sizeof(int));
 
     // Read login data
-
     xreadall(sock, toybuf, 152);
-    if (memcmp(toybuf, "NBDMAGIC\x00\x00\x42\x02\x81\x86\x12\x53", 16))
+    if (smemcmp(toybuf, "NBDMAGIC\x00\x00\x42\x02\x81\x86\x12\x53", 16))
       error_exit("bad login %s:%s", host, port);
-    devsize = SWAP_BE64(*(uint64_t *)(toybuf+16));
+    devsize = SWAP_BE64(*(unsigned long long *)(toybuf+16));
     flags = SWAP_BE32(*(int *)(toybuf+24));
 
-    // Set 4k block size.  Everything uses that these days.
-    ioctl(nbd, NBD_SET_BLKSIZE, 4096);
-    ioctl(nbd, NBD_SET_SIZE_BLOCKS, devsize/4096);
-    ioctl(nbd, NBD_CLEAR_SOCK);
+    // Use 4k block size
+    ioctl(TT.nbd, NBD_SET_BLKSIZE, TT.b);
+    ioctl(TT.nbd, NBD_SET_SIZE_BLOCKS, devsize/TT.b); // rounds down
+    ioctl(TT.nbd, NBD_CLEAR_SOCK);
 
-    // If the sucker was exported read only, respect that locally.
-    temp = (flags & 2) ? 1 : 0;
-    xioctl(nbd, BLKROSET, &temp);
+    // Locally respect read only exports
+    flags = (flags>>1)&1;
+    xioctl(TT.nbd, BLKROSET, &flags);
 
-    if (timeout && ioctl(nbd, NBD_SET_TIMEOUT, timeout)<0) break;
-    if (ioctl(nbd, NBD_SET_SOCK, sock) < 0) break;
+    if (timeout && ioctl(TT.nbd, NBD_SET_TIMEOUT, timeout)<0) break;
+    if (ioctl(TT.nbd, NBD_SET_SOCK, sock) < 0) break;
 
-    if (toys.optflags & FLAG_s) mlockall(MCL_CURRENT|MCL_FUTURE);
+    if (FLAG(s)) mlockall(MCL_CURRENT|MCL_FUTURE);
 
     // Open the device to force reread of the partition table.
-    if ((toys.optflags & FLAG_n) || !xfork()) {
+    if (!CFG_TOYBOX_FORK || !xfork()) {
       char *s = strrchr(device, '/');
       int i;
 
+      // Give device up to 10 seconds to come up
       sprintf(toybuf, "/sys/block/%.32s/pid", s ? s+1 : device);
-      // Is it up yet? (Give it 10 seconds.)
       for (i=0; i<100; i++) {
-        temp = open(toybuf, O_RDONLY);
-        if (temp == -1) msleep(100);
-        else {
-          close(temp);
-          break;
-        }
+        if (access(toybuf, F_OK)) break;
+        msleep(100);
       }
       close(open(device, O_RDONLY));
-      if (!(toys.optflags & FLAG_n)) exit(0);
+      if (CFG_TOYBOX_FORK) _exit(0);
     }
 
-    // Daemonize here.
-
-    if (daemon(0,0)) perror_exit("daemonize");
-
     // Process NBD requests until further notice.
 
-    if (ioctl(nbd, NBD_DO_IT)>=0 || errno==EBADR) break;
+    if (ioctl(TT.nbd, NBD_DO_IT)>=0 || errno==EBADR) break;
     close(sock);
+    ioctl(TT.nbd, NBD_CLEAR_QUE);
   }
 
   // Flush queue and exit.
-  ioctl(nbd, NBD_CLEAR_QUE);
-  ioctl(nbd, NBD_CLEAR_SOCK);
-  if (CFG_TOYBOX_FREE) close(nbd);
+  if (CFG_TOYBOX_FREE) close(TT.nbd);
 }
diff --git a/toys/other/nbd_server.c b/toys/other/nbd_server.c
new file mode 100644
index 0000000..98c1937
--- /dev/null
+++ b/toys/other/nbd_server.c
@@ -0,0 +1,88 @@
+/* nbd-server.c - network block device server
+ *
+ * Copyright 2022 Rob Landley <rob@landley.net>
+ *
+ * Not in SUSv4.
+ *
+ * See https://github.com/NetworkBlockDevice/nbd/blob/master/doc/proto.md
+
+// Work around dash in name trying to put - in function name.
+USE_NBD_SERVER(NEWTOY(nbd_server, "<1>1r", 0))
+USE_NBD_SERVER(OLDTOY(nbd-server, nbd_server, TOYFLAG_USR|TOYFLAG_BIN))
+
+config NBD_SERVER
+  bool "nbd-server"
+  default y
+  help
+    usage: nbd-server [-r] FILE
+
+    Serve a Network Block Device from FILE on stdin/out (ala inetd).
+
+    -r	Read only export
+*/
+
+// TODO: -r, block size, exit signal?
+
+#define FOR_nbd_server
+#include "toys.h"
+
+static int copy_loop(int from, int to, unsigned len)
+{
+  int try, rc = 0;
+
+  errno = 0;
+  while (len) {
+    xreadall(from, toybuf, try = len>4096 ? 4096 : len);
+    if (!rc && try != writeall(to, toybuf, try)) rc = errno;
+    len -= try;
+  }
+
+  return rc;
+}
+
+void nbd_server_main(void)
+{
+  unsigned long long *ll = (void *)toybuf, offset, handle;
+  unsigned short *ss = (void *)toybuf;
+  unsigned *uu = (void *)toybuf, type, length;
+  int fd = xopen(*toys.optargs, O_RDWR*!FLAG(r));
+
+  type = 1;
+  setsockopt(0, IPPROTO_TCP, TCP_NODELAY, &type, sizeof(int));
+
+  // Send original recipe negotiation, with device length and flags
+  memcpy(toybuf, "NBDMAGIC\x00\x00\x42\x02\x81\x86\x12\x53", 16);
+  ll[2] = SWAP_BE64(fdlength(fd));
+  uu[6] = SWAP_BE32(5+2*FLAG(r)); // has flags, can flush, maybe read only
+  xwrite(1, toybuf, 152);
+
+  // Simple loop, handles one request at a time with "simple" reply.
+  for (;;) {
+    // Fetch request into toybuf
+    xreadall(0, toybuf, 28);
+    if (SWAP_BE32(*uu) != 0x25609513) break;
+    type = SWAP_BE16(ss[3]);
+    handle = SWAP_BE64(ll[1]);
+    offset = SWAP_BE64(ll[2]);
+    length = SWAP_BE32(uu[6]);
+
+    // type 0 = read, 1 = write, 2 = disconnect, 3 = flush
+    if (type==2 || type>3) break;  // disconnect
+    if (type==3) { // flush
+      if (fdatasync(fd)) uu[1] = SWAP_BE32(errno);
+    } else {
+      xlseek(fd, offset, SEEK_SET);
+      if (type==1) { // write
+        uu[1] = copy_loop(0, fd, length);
+        ll[1] = SWAP_BE64(handle);
+      } else uu[1] = 0; // read never reports errors because send header first
+    }
+
+    // Simple reply in toybuf (handle stays put)
+    *uu = SWAP_BE32(0x67446698);
+    xwrite(1, toybuf, 16);
+
+    // Append read payload
+    if (!type) if (copy_loop(fd, 1, length)) break;
+  }
+}
diff --git a/toys/other/nsenter.c b/toys/other/nsenter.c
index d0c75d0..104ea1e 100644
--- a/toys/other/nsenter.c
+++ b/toys/other/nsenter.c
@@ -12,45 +12,52 @@
  *
 
 // Note: flags go in same order (right to left) for shared subset
-USE_NSENTER(NEWTOY(nsenter, "<1F(no-fork)t#<1(target)i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user);", TOYFLAG_USR|TOYFLAG_BIN))
-USE_UNSHARE(NEWTOY(unshare, "<1^f(fork);r(map-root-user);i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user);", TOYFLAG_USR|TOYFLAG_BIN))
+USE_NSENTER(NEWTOY(nsenter, "<1a(all)F(no-fork)t#<1(target)C(cgroup):; i(ipc):; m(mount):; n(net):; p(pid):; u(uts):; U(user):; ", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
+USE_UNSHARE(NEWTOY(unshare, "<1^a(all)f(fork)r(map-root-user)C(cgroup):; i(ipc):; m(mount):; n(net):; p(pid):; u(uts):; U(user):; ", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
 
 config UNSHARE
   bool "unshare"
   default y
-  depends on TOYBOX_CONTAINER
   help
     usage: unshare [-imnpuUr] COMMAND...
 
-    Create new container namespace(s) for this process and its children, so
-    some attribute is not shared with the parent process.
+    Create new container namespace(s) for this process and its children, allowing
+    the new set of processes to have a different view of the system than the
+    parent process.
 
+    -a	Unshare all supported namespaces
     -f	Fork command in the background (--fork)
+    -r	Become root (map current euid/egid to 0/0, implies -U) (--map-root-user)
+
+    Available namespaces:
+    -C	Control groups (--cgroup)
     -i	SysV IPC (message queues, semaphores, shared memory) (--ipc)
     -m	Mount/unmount tree (--mount)
     -n	Network address, sockets, routing, iptables (--net)
     -p	Process IDs and init (--pid)
-    -r	Become root (map current euid/egid to 0/0, implies -U) (--map-root-user)
     -u	Host and domain names (--uts)
     -U	UIDs, GIDs, capabilities (--user)
 
-    A namespace allows a set of processes to have a different view of the
-    system than other sets of processes.
+    Each namespace can take an optional argument, a persistent mountpoint usable
+    by the nsenter command to add new processes to that the namespace. (Specify
+    multiple namespaces to unshare separately, ala -c -i -m because -cim is -c
+    with persistent mount "im".)
 
 config NSENTER
   bool "nsenter"
-  depends on TOYBOX_CONTAINER
   default y
   help
     usage: nsenter [-t pid] [-F] [-i] [-m] [-n] [-p] [-u] [-U] COMMAND...
 
     Run COMMAND in an existing (set of) namespace(s).
 
-    -t	PID to take namespaces from    (--target)
+    -a	Enter all supported namespaces (--all)
     -F	don't fork, even if -p is used (--no-fork)
+    -t	PID to take namespaces from    (--target)
 
     The namespaces to switch are:
 
+    -C	Control groups (--cgroup)
     -i	SysV IPC: message queues, semaphores, shared memory (--ipc)
     -m	Mount/unmount tree (--mount)
     -n	Network address, sockets, routing, iptables (--net)
@@ -70,7 +77,7 @@
 #define setns(fd, nstype) syscall(SYS_setns, fd, nstype)
 
 GLOBALS(
-  char *Uupnmi[6];
+  char *UupnmiC[6];
   long t;
 )
 
@@ -86,28 +93,9 @@
   xclose(fd);
 }
 
-static void handle_r(int euid, int egid)
-{
-  int fd;
-
-  if ((fd = open("/proc/self/setgroups", O_WRONLY)) >= 0) {
-    xwrite(fd, "deny", 4);
-    close(fd);
-  }
-
-  write_ugid_map("/proc/self/uid_map", euid);
-  write_ugid_map("/proc/self/gid_map", egid);
-}
-
-static int test_r()
-{
-  return toys.optflags & FLAG_r;
-}
-
-static int test_f()
-{
-  return toys.optflags & FLAG_f;
-}
+static int test_a() { return FLAG(a); }
+static int test_r() { return FLAG(r); }
+static int test_f() { return FLAG(f); }
 
 // Shift back to the context GLOBALS lives in (I.E. matching the filename).
 #define FOR_nsenter
@@ -115,8 +103,9 @@
 
 void unshare_main(void)
 {
+  char *nsnames = "user\0uts\0pid\0net\0mnt\0ipc\0cgroup";
   unsigned flags[]={CLONE_NEWUSER, CLONE_NEWUTS, CLONE_NEWPID, CLONE_NEWNET,
-                    CLONE_NEWNS, CLONE_NEWIPC}, f = 0;
+                    CLONE_NEWNS, CLONE_NEWIPC, CLONE_NEWCGROUP}, f = 0;
   int i, fd;
 
   // Create new namespace(s)?
@@ -128,10 +117,17 @@
     if (test_r()) toys.optflags |= FLAG_U;
 
     for (i = 0; i<ARRAY_LEN(flags); i++)
-      if (toys.optflags & (1<<i)) f |= flags[i];
-
+      if (test_a() || (toys.optflags & (1<<i))) f |= flags[i];
     if (unshare(f)) perror_exit(0);
-    if (test_r()) handle_r(euid, egid);
+    if (test_r()) {
+      if ((fd = open("/proc/self/setgroups", O_WRONLY)) >= 0) {
+        xwrite(fd, "deny", 4);
+        close(fd);
+      }
+
+      write_ugid_map("/proc/self/uid_map", euid);
+      write_ugid_map("/proc/self/gid_map", egid);
+    }
 
     if (test_f()) {
       toys.exitval = xrun(toys.optargs);
@@ -140,25 +136,21 @@
     }
   // Bind to existing namespace(s)?
   } else if (CFG_NSENTER) {
-    char *nsnames = "user\0uts\0pid\0net\0mnt\0ipc";
+    for (i = 0; i<ARRAY_LEN(flags); i++, nsnames += strlen(nsnames)+1) {
+      if (FLAG(a) || (toys.optflags & (1<<i))) {
+        char *filename = TT.UupnmiC[i];
 
-    for (i = 0; i<ARRAY_LEN(flags); i++) {
-      char *filename = TT.Uupnmi[i];
-
-      if (toys.optflags & (1<<i)) {
         if (!filename || !*filename) {
-          if (!(toys.optflags & FLAG_t)) error_exit("need -t or =filename");
-          sprintf(toybuf, "/proc/%ld/ns/%s", TT.t, nsnames);
-          filename = toybuf;
+          if (!FLAG(t)) error_exit("need -t or =filename");
+          sprintf(filename = toybuf, "/proc/%ld/ns/%s", TT.t, nsnames);
         }
 
         if (setns(fd = xopenro(filename), flags[i])) perror_exit("setns");
         close(fd);
       }
-      nsnames += strlen(nsnames)+1;
     }
 
-    if ((toys.optflags & FLAG_p) && !(toys.optflags & FLAG_F)) {
+    if (FLAG(p) && !FLAG(F)) {
       toys.exitval = xrun(toys.optargs);
 
       return;
diff --git a/toys/other/oneit.c b/toys/other/oneit.c
index 4c8bb1f..c0b0c09 100644
--- a/toys/other/oneit.c
+++ b/toys/other/oneit.c
@@ -65,13 +65,37 @@
 void oneit_main(void)
 {
   int i, pid, pipes[] = {SIGUSR1, SIGUSR2, SIGTERM, SIGINT};
+  char *ss = toybuf+5;
 
   // Setup signal handlers for signals of interest
   for (i = 0; i<ARRAY_LEN(pipes); i++) xsignal(pipes[i], oneit_signaled);
 
+  // Autodetect console from sysfs if no -c
+  memcpy(toybuf, "/dev/", 5);
+  i = sizeof(toybuf)-6;
+  if (!TT.c && (TT.c = readfile("/sys/class/tty/console/active", ss, i))) {
+    // Take last entry, remove newline terminator
+    while (TT.c[i = strcspn(TT.c, " \n")]) {
+      TT.c[i++] = 0;
+      if (TT.c[i]) TT.c += i;
+      else break;
+    }
+    // Ensure exactly one /dev prefix
+    strstart(&TT.c, "/dev/");
+    memmove(toybuf+5, TT.c, strlen(TT.c));
+    TT.c = toybuf;
+  }
+
+  // Redirect stdin/out/err. Remember, O_CLOEXEC is backwards for xopen()
+  close(0);
+  xopen_stdio(TT.c ? : "/dev/tty0", O_RDWR|O_CLOEXEC);
+  close(1);
+  dup(0);
+  close(2);
+  dup(0);
+
   if (FLAG(3)) {
     // Ensure next available filehandles are #3 and #4
-    while (xopen_stdio("/", 0) < 3);
     close(3);
     close(4);
     xpipe(pipes);
@@ -93,13 +117,8 @@
 
       oneit_signaled(FLAG(p) ? SIGUSR2 : SIGTERM);
     } else {
-      // Redirect stdio to TT.c, with new session ID, so ctrl-c works.
+      // new session ID in child, so ctrl-c works.
       setsid();
-      for (i=0; i<3; i++) {
-        close(i);
-        // Remember, O_CLOEXEC is backwards for xopen()
-        xopen_stdio(TT.c ? : "/dev/tty0", O_RDWR|O_CLOEXEC);
-      }
 
       // Can't xexec() here, we vforked so we don't want to error_exit().
       toy_exec(toys.optargs);
diff --git a/toys/other/openvt.c b/toys/other/openvt.c
index 8210587..66d8a36 100644
--- a/toys/other/openvt.c
+++ b/toys/other/openvt.c
@@ -6,7 +6,7 @@
  * No Standard
 
 USE_OPENVT(NEWTOY(openvt, "^<1c#<1>63sw", TOYFLAG_BIN|TOYFLAG_NEEDROOT))
-USE_CHVT(NEWTOY(chvt, "<1", TOYFLAG_USR|TOYFLAG_BIN))
+USE_CHVT(NEWTOY(chvt, "<1>1", TOYFLAG_USR|TOYFLAG_BIN))
 USE_DEALLOCVT(NEWTOY(deallocvt, ">1", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_NEEDROOT))
 
 config OPENVT
diff --git a/toys/other/pmap.c b/toys/other/pmap.c
index d222f01..91e2827 100644
--- a/toys/other/pmap.c
+++ b/toys/other/pmap.c
@@ -17,7 +17,7 @@
 
     Report the memory map of a process or processes.
 
-    -q	Show full paths
+    -p	Show full paths
     -q	Do not show header or footer
     -x	Show the extended format
 */
@@ -32,7 +32,7 @@
 
   for (optargs = toys.optargs; *optargs; optargs++) {
     long long start, end, pss, tpss=0, dirty, tdirty=0, swap, tswap=0, total=0;
-    char *name = 0, *k = FLAG(x) ? "" : "K", mode[5];
+    char *name = 0, *k = "K"+FLAG(x), mode[5];
     pid_t pid = atolx(*optargs);
     int extras = 0, off, count;
     FILE *fp;
@@ -63,7 +63,7 @@
         name = line[off] ? line+off : "  [anon]\n";
         if (mode[3] == 'p') mode[3] = '-';
         total += end = (end-start)/1024;
-        printf("%0*llx % *lld%s ", (int)(2*sizeof(long)), start, 6+!!FLAG(x),
+        printf("%0*llx % *lld%s ", (int)(2*sizeof(long)), start, 6+FLAG(x),
             end, k);
         if (FLAG(x)) {
           strcpy(toybuf, name);
@@ -92,7 +92,7 @@
         xprintf("----------------  ------  ------  ------  ------\n" +
             ((sizeof(long)==4)?8:0));
       }
-      printf("total% *lld%s", 2*(int)(sizeof(long)+1)+!!FLAG(x), total, k);
+      printf("total% *lld%s", 2*(int)(sizeof(long)+1)+FLAG(x), total, k);
       if (FLAG(x)) printf("% 8lld% 8lld% 8lld", tpss, tdirty, tswap);
       xputc('\n');
     }
diff --git a/toys/other/pwgen.c b/toys/other/pwgen.c
index c34daf5..7362756 100644
--- a/toys/other/pwgen.c
+++ b/toys/other/pwgen.c
@@ -51,7 +51,7 @@
   for (jj = 0; jj<count; jj++) {
     for (ii = 0; ii<length;) {
       // Don't fetch more random than necessary, give each byte 2 tries to fit
-      if (!rand) xgetrandom(randbuf, rand = sizeof(randbuf), 0);
+      if (!rand) xgetrandom(randbuf, rand = sizeof(randbuf));
       c = 33+randbuf[--rand]%93; // remainder 69 makes >102 less likely
       if (FLAG(s)) randbuf[rand] = 0;
 
diff --git a/toys/other/readelf.c b/toys/other/readelf.c
index 29e2724..1db6b69 100644
--- a/toys/other/readelf.c
+++ b/toys/other/readelf.c
@@ -124,6 +124,8 @@
   char *end;
   unsigned i;
 
+  if (!spec) return 0;
+
   // Valid section number?
   i = estrtol(spec, &end, 0);
   if (!errno && !*end && i<TT.shnum) return get_sh(i, s);
@@ -355,7 +357,7 @@
   char *hdr = TT.elf;
   int type, machine, version, flags, entry, ehsize, phnum, shstrndx, i, j, w;
 
-  if (TT.size < 45 || memcmp(hdr, "\177ELF", 4)) 
+  if (TT.size < 45 || smemcmp(hdr, "\177ELF", 4))
     return error_msg("%s: not ELF", TT.f);
 
   TT.bits = hdr[4] - 1;
@@ -453,7 +455,7 @@
              s.entsize, sh_flags, s.link, s.info, s.addralign);
     }
   }
-  if (FLAG(S) && TT.shnum) 
+  if (FLAG(S) && TT.shnum)
     printf("Key:\n  (W)rite, (A)lloc, e(X)ecute, (M)erge, (S)trings, (I)nfo\n"
            "  (L)ink order, (O)S, (G)roup, (T)LS, (C)ompressed, x=unknown\n");
 
@@ -574,7 +576,7 @@
     }
   }
 
-  if (FLAG(x) && find_section(TT.x, &s)) {
+  if (find_section(TT.x, &s)) {
     char *p = TT.elf+s.offset;
     long offset = 0;
 
@@ -592,7 +594,7 @@
     xputc('\n');
   }
 
-  if (FLAG(p) && find_section(TT.p, &s)) {
+  if (find_section(TT.p, &s)) {
     char *begin = TT.elf+s.offset, *end = begin + s.size, *p = begin;
     int any = 0;
 
diff --git a/toys/other/readlink.c b/toys/other/readlink.c
index 3155dcc..2acdd55 100644
--- a/toys/other/readlink.c
+++ b/toys/other/readlink.c
@@ -2,9 +2,8 @@
  *
  * Copyright 2007 Rob Landley <rob@landley.net>
 
-// -ef positions match ABS_FILE ABS_PATH
-USE_READLINK(NEWTOY(readlink, "<1nqmef(canonicalize)[-mef]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_REALPATH(OLDTOY(realpath, readlink, TOYFLAG_USR|TOYFLAG_BIN))
+USE_READLINK(NEWTOY(readlink, "<1vnf(canonicalize)emqz[-mef][-qv]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_REALPATH(NEWTOY(realpath, "<1(relative-base):R(relative-to):s(no-symlinks)LPemqz[-Ps][-LP][-me]", TOYFLAG_USR|TOYFLAG_BIN))
 
 config READLINK
   bool "readlink"
@@ -20,36 +19,108 @@
     -f	Full path (fail if directory missing)
     -m	Ignore missing entries, show where it would be
     -n	No trailing newline
-    -q	Quiet (no output, just error code)
+    -q	Quiet (no error messages)
+    -z	NUL instead of newline
 
 config REALPATH
   bool "realpath"
   default y
   help
-    usage: realpath FILE...
+    usage: realpath [-LPemqsz] [--relative-base DIR] [-R DIR] FILE...
 
     Display the canonical absolute pathname
+
+    -R Show ../path relative to DIR (--relative-to)
+    -L Logical path (resolve .. before symlinks)
+    -P Physical path (default)
+    -e Canonical path to existing entry (fail if missing)
+    -m Ignore missing entries, show where it would be
+    -q Quiet (no error messages)
+    -s Don't expand symlinks
+    -z NUL instead of newline
+    --relative-base  If path under DIR trim off prefix
 */
 
-#define FOR_readlink
+#define FOR_realpath
 #define FORCE_FLAGS
+#define TT this.readlink // workaround: first FOR_ doesn't match filename
 #include "toys.h"
 
-void readlink_main(void)
+GLOBALS(
+  char *R, *relative_base;
+)
+
+// test TT.relative_base -RsmLP
+// Trim .. out early for -s and -L. TODO: in place in the input string.
+
+static char *resolve(char *arg)
+{
+  int flags = FLAG(e) ? ABS_FILE : FLAG(m) ? 0 : ABS_PATH;
+  char *s, *ss = 0, *dd = 0;
+
+  if (FLAG(s)) flags |= ABS_KEEP;
+  else if (FLAG(L)) arg = dd = xabspath(arg, ABS_KEEP);
+  if (!(s = xabspath(arg, flags)) && !FLAG(q)) perror_msg("%s", arg);
+  free(dd);
+
+  // Trim off this prefix if path under here
+
+  if (TT.relative_base) {
+    ss = s;
+    if (strstart(&ss, TT.relative_base) && (!*ss || *ss=='/')) {
+      if (*ss=='/') ss++;
+      ss = xstrdup(!*ss ? "." : ss);
+    } else ss = 0;
+  } else if (TT.R) ss = relative_path(TT.R, s, 0);
+  if (ss) {
+    free(s);
+    s = ss;
+  }
+
+  return s;
+}
+
+// Resolve command line arguments that can't take part in their own resolution
+static char *presolve(char **s)
+{
+  char *ss = *s;
+
+  if (ss) {
+    *s = 0;
+    if (!(*s = resolve(ss))) xexit();
+  }
+
+  return ss;
+}
+
+// Uses realpath flag context: flags (1 = resolve, 2 = -n)
+static void do_paths(int flags)
 {
   char **arg, *s;
 
-  if (toys.which->name[3]=='l') toys.optflags |= FLAG_f;
-  for (arg = toys.optargs; *arg; arg++) {
-    // Calculating full canonical path?
-    // Take advantage of flag positions: m = 0, f = ABS_PATH, e = ABS_FILE
-    if (toys.optflags & (FLAG_f|FLAG_e|FLAG_m))
-      s = xabspath(*arg, toys.optflags&(FLAG_f|FLAG_e));
-    else s = xreadlink(*arg);
+  if (!presolve(&TT.relative_base)) presolve(&TT.R);
 
-    if (s) {
-      if (!FLAG(q)) xprintf("%s%s", s, (FLAG(n) && !arg[1]) ? "" : "\n");
-      free(s);
-    } else toys.exitval = 1;
+  for (arg = toys.optargs; *arg; arg++) {
+    if (!(s = (flags&1) ? resolve(*arg) : xreadlink(*arg))) toys.exitval = 1;
+    else xprintf(((flags&2) && !arg[1]) ? "%s" : "%s%c", s, '\n'*!FLAG(z));
+    free(s);
   }
 }
+
+void realpath_main(void)
+{
+  do_paths(1);
+}
+
+#define FOR_readlink
+#include "generated/flags.h"
+
+// Convert readlink flag context to realpath (feeding in -nf separately)
+void readlink_main(void)
+{
+  int nf = (toys.optflags/FLAG_f)|!!(FLAG(m)|FLAG(e));
+
+  toys.optflags &= FLAG_f-1;
+  if (!FLAG(v)) toys.optflags |= FLAG_q;
+  do_paths(nf);
+}
diff --git a/toys/other/sha3sum.c b/toys/other/sha3sum.c
index ee951e0..b35c57f 100644
--- a/toys/other/sha3sum.c
+++ b/toys/other/sha3sum.c
@@ -6,7 +6,6 @@
  * https://csrc.nist.gov/publications/detail/fips/202/final
  * https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf
 
-// Depends on FLAG(b) being 4
 USE_SHA3SUM(NEWTOY(sha3sum, "bSa#<128>512=224", TOYFLAG_USR|TOYFLAG_BIN))
 
 config SHA3SUM
@@ -89,8 +88,7 @@
   }
   memset(buf, 0, sizeof(buf));
 
-  // Depends on FLAG(b) being 4
-  xprintf("  %s\n"+FLAG(b), name);
+  xprintf("  %s\n"+(FLAG(b)<<2), name);
 }
 
 // TODO test 224 256 384 512, and shake 128 256
diff --git a/toys/other/shred.c b/toys/other/shred.c
index 1932f75..9c13f6b 100644
--- a/toys/other/shred.c
+++ b/toys/other/shred.c
@@ -90,7 +90,7 @@
       throw = sizeof(toybuf);
       if (FLAG(x) && len-pos < throw) throw = len-pos;
 
-      if (iter != TT.n) xgetrandom(toybuf, throw, 0);
+      if (iter != TT.n) xgetrandom(toybuf, throw);
       if (throw != writeall(fd, toybuf, throw)) perror_msg_raw(*try);
       pos += throw;
     }
diff --git a/toys/other/shuf.c b/toys/other/shuf.c
new file mode 100644
index 0000000..fe8230f
--- /dev/null
+++ b/toys/other/shuf.c
@@ -0,0 +1,63 @@
+/* shuf.c - Output lines in random order.
+ *
+ * Copyright 2023 Rob Landley <rob@landley.net>
+ *
+ * See https://man7.org/linux/man-pages/man1/shuf.1.html
+
+USE_SHUF(NEWTOY(shuf, "zen#<0", TOYFLAG_USR|TOYFLAG_BIN))
+
+config SHUF
+  bool "shuf"
+  default y
+  help
+    usage: shuf [-ze] [-n COUNT] [FILE...]
+
+    Write lines of input to output in random order.
+
+    -z	Input/output lines are NUL terminated.
+    -n	Stop after COUNT many output lines.
+    -e	Echo mode: arguments are inputs to shuffle, not files to read.
+*/
+
+#define FOR_shuf
+#include "toys.h"
+
+GLOBALS(
+  long n;
+
+  char **lines;
+  long count;
+)
+
+static void do_shuf_line(char **pline, long len)
+{
+  if (!pline) return;
+  if (!(TT.count&255))
+    TT.lines = xrealloc(TT.lines, sizeof(void *)*(TT.count+256));
+  TT.lines[TT.count++] = *pline; // TODO: repack?
+  *pline = 0;
+}
+
+static void do_shuf(int fd, char *name)
+{
+  do_lines(fd, '\n'*!FLAG(z), do_shuf_line);
+}
+
+void shuf_main(void)
+{
+  if (FLAG(e)) {
+    TT.lines = toys.optargs;
+    TT.count = toys.optc;
+  } else loopfiles(toys.optargs, do_shuf);
+
+  if (!FLAG(n) || TT.n>TT.count) TT.n = TT.count;
+
+  srandom(millitime());
+  while (TT.n--) {
+    long ll = random()%TT.count;
+    writeall(1, TT.lines[ll], strlen(TT.lines[ll])+FLAG(z));
+    if (!FLAG(e)) free(TT.lines[ll]);
+    else if (!FLAG(z)) writeall(1, "\n", 1);
+    TT.lines[ll] = TT.lines[--TT.count];
+  }
+}
diff --git a/toys/other/stat.c b/toys/other/stat.c
index 98f27ed..463aa46 100644
--- a/toys/other/stat.c
+++ b/toys/other/stat.c
@@ -157,13 +157,13 @@
 
 void stat_main(void)
 {
-  int flagf = FLAG(f), i;
+  int i;
   char *format, *f;
 
-  if (FLAG(t)) format = flagf
+  if (FLAG(t)) format = FLAG(f)
     ? "%n %i %l %t %s %S %b %f %a %c %d"
     : "%n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %o";
-  else format = flagf
+  else format = FLAG(f)
     ? "  File: \"%n\"\n    ID: %i Namelen: %l    Type: %T\n"
       "Block Size: %s    Fundamental block size: %S\n"
       "Blocks: Total: %b\tFree: %f\tAvailable: %a\n"
@@ -180,8 +180,8 @@
 
     // stat the file or filesystem
     TT.file = toys.optargs[i];
-    if (flagf && !statfs(TT.file, (void *)&TT.stat));
-    else if (flagf || (FLAG(L) ? stat : lstat)(TT.file, (void *)&TT.stat)) {
+    if (FLAG(f) && !statfs(TT.file, (void *)&TT.stat));
+    else if (FLAG(f) || (FLAG(L) ? stat : lstat)(TT.file, (void *)&TT.stat)) {
       perror_msg("'%s'", TT.file);
       continue;
     }
@@ -195,7 +195,7 @@
         TT.patlen = f-TT.pattern;
         if (!*f || TT.patlen>99) error_exit("bad %s", TT.pattern);
         if (*f == 'n') strout(TT.file);
-        else if (flagf) print_statfs(*f);
+        else if (FLAG(f)) print_statfs(*f);
         else print_stat(*f);
       }
     }
diff --git a/toys/other/swapoff.c b/toys/other/swapoff.c
index fb17130..bd6a41a 100644
--- a/toys/other/swapoff.c
+++ b/toys/other/swapoff.c
@@ -2,20 +2,40 @@
  *
  * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
 
-USE_SWAPOFF(NEWTOY(swapoff, "<1>1", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
+USE_SWAPOFF(NEWTOY(swapoff, "<1>1av", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
 
 config SWAPOFF
   bool "swapoff"
   default y
   help
-    usage: swapoff swapregion
+    usage: swapoff FILE
 
-    Disable swapping on a given swapregion.
+    Disable swapping on a device or file.
 */
 
+#define FOR_swapoff
 #include "toys.h"
 
+static void xswapoff(char *str)
+{
+  if (FLAG(v)) printf("swapoff %s", str);
+  if (swapoff(str)) perror_msg("failed to remove swaparea");
+}
+
 void swapoff_main(void)
 {
-  if (swapoff(toys.optargs[0])) perror_exit("failed to remove swaparea");
+  char *ss, *line, **args;
+  FILE *fp;
+
+  if (FLAG(a) && (fp = fopen("/proc/swaps", "r"))) {
+    while ((line = xgetline(fp))) {
+      if (*line != '/' || !(ss = strchr(line, ' '))) continue;
+      *ss = 0;
+      octal_deslash(line);
+      xswapoff(line);
+      free(line);
+    }
+    fclose(fp);
+  }
+  for (args = toys.optargs; *args; args++) xswapoff(*args);
 }
diff --git a/toys/other/taskset.c b/toys/other/taskset.c
index 2a9ae02..a3d0ffb 100644
--- a/toys/other/taskset.c
+++ b/toys/other/taskset.c
@@ -2,7 +2,7 @@
  *
  * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
 
-USE_TASKSET(NEWTOY(taskset, "<1^pa", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
+USE_TASKSET(NEWTOY(taskset, "<1^pa", TOYFLAG_USR|TOYFLAG_BIN))
 USE_NPROC(NEWTOY(nproc, "(all)", TOYFLAG_USR|TOYFLAG_BIN))
 
 config NPROC
@@ -34,36 +34,31 @@
 #define FOR_taskset
 #include "toys.h"
 
+// mask is array of long which makes layout a bit weird on big endian systems
 #define sched_setaffinity(pid, size, cpuset) \
   syscall(__NR_sched_setaffinity, (pid_t)pid, (size_t)size, (void *)cpuset)
 #define sched_getaffinity(pid, size, cpuset) \
   syscall(__NR_sched_getaffinity, (pid_t)pid, (size_t)size, (void *)cpuset)
 
-// mask is an array of long, which makes the layout a bit weird on big
-// endian systems but as long as it's consistent...
-
 static void do_taskset(pid_t pid, int quiet)
 {
   unsigned long *mask = (unsigned long *)toybuf;
-  char *s = *toys.optargs, *failed = "failed to %s %d's affinity";
+  char *s, *failed = "failed to %s pid %d's affinity";
   int i, j, k;
 
+  // loop through twice to display before/after affinity masks
   for (i=0; ; i++) {
     if (!quiet) {
-      int j = sizeof(toybuf), flag = 0;
-
       if (-1 == sched_getaffinity(pid, sizeof(toybuf), (void *)mask))
         perror_exit(failed, "get", pid);
 
       printf("pid %d's %s affinity mask: ", pid, i ? "new" : "current");
 
-      while (j--) {
-        int x = 255 & (mask[j/sizeof(long)] >> (8*(j&(sizeof(long)-1))));
-
-        if (flag) printf("%02x", x);
-        else if (x) {
-          flag++;
-          printf("%x", x);
+      for (j = sizeof(toybuf)/sizeof(long), k = 0; --j>=0;) {
+        if (k) printf("%0*lx", (int)(2*sizeof(long)), mask[j]);
+        else if (mask[j]) {
+          k++;
+          printf("%lx", mask[j]);
         }
       }
       putchar('\n');
@@ -71,6 +66,7 @@
 
     if (i || toys.optc < 2) return;
 
+    // Convert hex strong to mask[] bits
     memset(toybuf, 0, sizeof(toybuf));
     k = strlen(s = *toys.optargs);
     s += k;
@@ -89,26 +85,25 @@
 
 static int task_callback(struct dirtree *new)
 {
-  if (!new->parent) return DIRTREE_RECURSE;
-  if (isdigit(*new->name)) do_taskset(atoi(new->name), 0);
+  if (!new->parent) return DIRTREE_RECURSE|DIRTREE_SHUTUP|DIRTREE_PROC;
+  do_taskset(atoi(new->name), 0);
 
   return 0;
 }
 
 void taskset_main(void)
 {
-  if (!(toys.optflags & FLAG_p)) {
+  if (!FLAG(p)) {
     if (toys.optc < 2) error_exit("Needs 2 args");
     do_taskset(getpid(), 1);
     xexec(toys.optargs+1);
   } else {
-    char *c;
+    char *c, buf[33];
     pid_t pid = strtol(toys.optargs[toys.optc-1], &c, 10);
 
-    if (*c) error_exit("Not int %s", toys.optargs[1]);
+    if (*c) error_exit("Not int %s", toys.optargs[toys.optc-1]);
 
-    if (toys.optflags & FLAG_a) {
-      char buf[33];
+    if (FLAG(a)) {
       sprintf(buf, "/proc/%ld/task/", (long)pid);
       dirtree_read(buf, task_callback);
     } else do_taskset(pid, 0);
@@ -118,15 +113,26 @@
 void nproc_main(void)
 {
   unsigned i, j, nproc = 0;
+  DIR *dd;
 
   // This can only detect 32768 processors. Call getaffinity and count bits.
-  if (!toys.optflags && -1!=sched_getaffinity(getpid(), 4096, toybuf)) {
+  if (!toys.optflags && -1!=sched_getaffinity(getpid(), 4096, toybuf))
     for (i = 0; i<4096; i++)
       if (toybuf[i]) for (j=0; j<8; j++) if (toybuf[i]&(1<<j)) nproc++;
+
+  // If getaffinity failed or --all, count cpu entries in sysfs
+  // (/proc/cpuinfo filters out hot-unplugged CPUs, sysfs doesn't)
+  if (!nproc && (dd = opendir("/sys/devices/system/cpu"))) {
+    struct dirent *de;
+    char *ss;
+
+    while ((de = readdir(dd))) {
+      if (smemcmp(de->d_name, "cpu", 3)) continue;
+      for (ss = de->d_name+3; isdigit(*ss); ss++);
+      if (!*ss) nproc++;
+    }
+    closedir(dd);
   }
 
-  // If getaffinity failed or --all, count cpu entries in proc
-  if (!nproc) nproc = sysconf(_SC_NPROCESSORS_CONF);
-
-  xprintf("%u\n", nproc);
+  xprintf("%u\n", nproc ? : 1);
 }
diff --git a/toys/other/timeout.c b/toys/other/timeout.c
index e93a806..ed4956a 100644
--- a/toys/other/timeout.c
+++ b/toys/other/timeout.c
@@ -4,13 +4,13 @@
  *
  * No standard
 
-USE_TIMEOUT(NEWTOY(timeout, "<2^(foreground)(preserve-status)vk:s(signal):", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(125)))
+USE_TIMEOUT(NEWTOY(timeout, "<2^(foreground)(preserve-status)vk:s(signal):i", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(125)))
 
 config TIMEOUT
   bool "timeout"
   default y
   help
-    usage: timeout [-k DURATION] [-s SIGNAL] DURATION COMMAND...
+    usage: timeout [-i] [-k DURATION] [-s SIGNAL] DURATION COMMAND...
 
     Run command line as a child process, sending child a signal if the
     command doesn't exit soon enough.
@@ -18,8 +18,9 @@
     DURATION can be a decimal fraction. An optional suffix can be "m"
     (minutes), "h" (hours), "d" (days), or "s" (seconds, the default).
 
-    -s	Send specified signal (default TERM)
+    -i	Only kill for inactivity (restart timeout when command produces output)
     -k	Send KILL signal if child still running this long after first signal
+    -s	Send specified signal (default TERM)
     -v	Verbose
     --foreground       Don't create new process group
     --preserve-status  Exit with the child's exit status
@@ -31,54 +32,77 @@
 GLOBALS(
   char *s, *k;
 
-  int nextsig;
-  pid_t pid;
-  struct timespec kts;
-  struct itimerspec its;
-  timer_t timer;
+  struct pollfd pfd;
+  sigjmp_buf sj;
+  int fds[2], pid;
 )
 
-static void handler(int i)
+static void handler(int sig)
 {
-  if (FLAG(v))
-    fprintf(stderr, "timeout pid %d signal %d\n", TT.pid, TT.nextsig);
+  siglongjmp(TT.sj, 1);
+}
 
-  toys.exitval = (TT.nextsig==9) ? 137 : 124;
-  kill(TT.pid, TT.nextsig);
-  if (TT.k) {
-    TT.k = 0;
-    TT.nextsig = SIGKILL;
-    xsignal(SIGALRM, handler);
-    TT.its.it_value = TT.kts;
-    if (timer_settime(TT.timer, 0, &TT.its, 0)) perror_exit("timer_settime");
-  }
+static long nantomil(struct timespec *ts)
+{
+  return ts->tv_sec*1000+ts->tv_nsec/1000000;
+}
+
+static void callback(char *argv[])
+{
+  xsignal(SIGCHLD, SIG_DFL);
+  if (!FLAG(foreground)) setpgid(0, 0);
 }
 
 void timeout_main(void)
 {
-  struct sigevent se = { .sigev_notify = SIGEV_SIGNAL, .sigev_signo = SIGALRM };
+  int ii, ms, nextsig = SIGTERM;
+  struct timespec tts, kts;
 
   // Use same ARGFAIL value for any remaining parsing errors
   toys.exitval = 125;
-  xparsetimespec(*toys.optargs, &TT.its.it_value);
-  if (TT.k) xparsetimespec(TT.k, &TT.kts);
-
-  TT.nextsig = SIGTERM;
-  if (TT.s && -1 == (TT.nextsig = sig_to_num(TT.s)))
-    error_exit("bad -s: '%s'", TT.s);
-
-  if (!FLAG(foreground)) setpgid(0, 0);
+  xparsetimespec(*toys.optargs, &tts);
+  if (TT.k) xparsetimespec(TT.k, &kts);
+  if (TT.s && -1==(nextsig = sig_to_num(TT.s))) error_exit("bad -s: '%s'",TT.s);
 
   toys.exitval = 0;
-  if (!(TT.pid = XVFORK())) xexec(toys.optargs+1);
-  else {
-    int status;
+  TT.pfd.events = POLLIN;
+  TT.fds[1] = -1;
+  if (sigsetjmp(TT.sj, 1)) goto done;
+  xsignal_flags(SIGCHLD, handler, SA_NOCLDSTOP);
 
-    xsignal(SIGALRM, handler);
-    if (timer_create(CLOCK_MONOTONIC, &se, &TT.timer)) perror_exit("timer");
-    if (timer_settime(TT.timer, 0, &TT.its, 0)) perror_exit("timer_settime");
+  TT.pid = xpopen_setup(toys.optargs+1, FLAG(i) ? TT.fds : 0, callback);
+  xsignal(SIGTTIN, SIG_IGN);
+  xsignal(SIGTTOU, SIG_IGN);
+  xsignal(SIGTSTP, SIG_IGN);
+  if (!FLAG(i)) xpipe(TT.fds);
+  TT.pfd.fd = TT.fds[1];
+  ms = nantomil(&tts);
+  for (;;) {
+    if (1 != xpoll(&TT.pfd, 1, ms)) {
+      if (FLAG(v))
+        perror_msg("sending signal %s to command %s", num_to_sig(nextsig),
+          toys.optargs[1]);
+      toys.exitval = (nextsig==9) ? 137 : 124;
+      kill(FLAG(foreground) ? TT.pid : -TT.pid, nextsig);
+      if (!TT.k || nextsig==SIGKILL) break;
+      nextsig = SIGKILL;
+      ms = nantomil(&kts);
 
-    status = xwaitpid(TT.pid);
-    if (FLAG(preserve_status) || !toys.exitval) toys.exitval = status;
+      continue;
+    }
+    if (TT.pfd.revents&POLLIN) {
+      errno = 0;
+      if (1>(ii = read(TT.fds[1], toybuf, sizeof(toybuf)))) {
+        if (errno==EINTR) continue;
+        break;
+      }
+      writeall(1, toybuf, ii);
+    }
+    if (TT.pfd.revents&POLLHUP) break;
   }
+done:
+  xsignal(SIGCHLD, SIG_DFL);
+  ii = xpclose_both(TT.pid, TT.fds);
+
+  if (FLAG(preserve_status) || !toys.exitval) toys.exitval = ii;
 }
diff --git a/toys/other/uptime.c b/toys/other/uptime.c
index 6c0c805..237bba6 100644
--- a/toys/other/uptime.c
+++ b/toys/other/uptime.c
@@ -9,7 +9,6 @@
 config UPTIME
   bool "uptime"
   default y
-  depends on TOYBOX_UTMPX
   help
     usage: uptime [-ps]
 
diff --git a/toys/other/usleep.c b/toys/other/usleep.c
index 6040cc0..e09a17c 100644
--- a/toys/other/usleep.c
+++ b/toys/other/usleep.c
@@ -2,7 +2,7 @@
  *
  * Copyright 2012 Elie De Brauwer <eliedebrauwer@gmail.com>
 
-USE_USLEEP(NEWTOY(usleep, "<1", TOYFLAG_BIN))
+USE_USLEEP(NEWTOY(usleep, "<1>1", TOYFLAG_BIN))
 
 config USLEEP
   bool "usleep"
diff --git a/toys/other/vmstat.c b/toys/other/vmstat.c
index d5cf569..94502f1 100644
--- a/toys/other/vmstat.c
+++ b/toys/other/vmstat.c
@@ -29,125 +29,124 @@
 #include "toys.h"
 
 struct vmstat_proc {
-  // From /proc/stat (jiffies)
-  uint64_t user, nice, sys, idle, wait, irq, sirq, intr, ctxt, running, blocked;
-  // From /proc/meminfo (units are kb)
-  uint64_t memfree, buffers, cached, swapfree, swaptotal;
-  // From /proc/vmstat (units are kb)
-  uint64_t io_in, io_out;
-  // From /proc/vmstat (units are pages)
-  uint64_t swap_in, swap_out;
+  unsigned long long
+    // From /proc/stat (jiffies) 0-10
+    user, nice, sys, idle, wait, irq, sirq, intr, ctxt, running, blocked,
+    // From /proc/meminfo (units are kb) 11-16
+    memfree, buffers, cached, swapfree, swaptotal, reclaimable,
+    // From /proc/vmstat (units are kb) 17-18
+    io_in, io_out,
+    // From /proc/vmstat (units are pages) 19-20
+    swap_in, swap_out;
 };
 
 // All the elements of vmstat_proc are the same size, so we can populate it as
 // a big array, then read the elements back out by name
-static void get_vmstat_proc(struct vmstat_proc *vmstat_proc)
+static void get_vmstat_proc(struct vmstat_proc *vmsp)
 {
-  char *vmstuff[] = { "/proc/stat", "cpu ", 0, 0, 0, 0, 0, 0,
-    "intr ", "ctxt ", "procs_running ", "procs_blocked ", "/proc/meminfo",
-    "MemFree: ", "Buffers: ", "Cached: ", "SwapFree: ", "SwapTotal: ",
+  char *vmstuff[] = { "/proc/stat", "cpu ", 0, 0, 0, 0, 0, 0, "intr ", "ctxt ",
+    "procs_running ", "procs_blocked ", "/proc/meminfo", "MemFree:",
+    "Buffers:", "Cached:", "SwapFree:", "SwapTotal:", "SReclaimable:",
     "/proc/vmstat", "pgpgin ", "pgpgout ", "pswpin ", "pswpout " };
-  uint64_t *new = (uint64_t *)vmstat_proc;
-  char *p = p, *name = name, *file = NULL;
+  unsigned long long *new = (void *)vmsp;
+  char *p = 0, *name = name, *file = 0;
   int i, j;
 
-  // We use vmstuff to fill out vmstat_proc as an array of uint64_t:
+  // We use vmstuff to fill out vmstat_proc as an array of long long:
   //   Strings starting with / are the file to find next entries in
   //   Any other string is a key to search for, with decimal value right after
   //   0 means parse another value on same line as last key
 
-  for (i = 0; i<ARRAY_LEN(vmstuff); i++) {
-    if (!vmstuff[i]) p++;
+  memset(new, 0, sizeof(struct vmstat_proc));
+  for (i = j = 0; i<ARRAY_LEN(vmstuff); i++) {
+    if (!vmstuff[i]) p++; // Read next entry on same line
     else if (*vmstuff[i] == '/') {
-      // /proc/stat for a 48-core machine doesn't fit in toybuf.
       free(file);
       file = xreadfile(name = vmstuff[i], 0, 0);
 
       continue;
-    } else p = strafter(file, vmstuff[i]);
-    if (!p || 1!=sscanf(p, "%"PRIu64"%n", new++, &j))
-      error_exit("Bad %sin %s: %s", vmstuff[i], name, p ? p : "");
-    p += j;
+    } else if (file && !(p = strafter(file, vmstuff[i]))) {
+      free(file);
+      file = 0;
+    }
+    if (!file) new++;
+    else if (1==sscanf(p, "%llu%n", new++, &j)) p += j;
   }
   free(file);
+
+  // combine some fields we display as aggregates
+  vmsp->running--; // Don't include ourselves
+  vmsp->user += vmsp->nice;
+  vmsp->sys += vmsp->irq + vmsp->sirq;
+  vmsp->swaptotal -= vmsp->swapfree;
+  vmsp->cached += vmsp->reclaimable;
 }
 
 void vmstat_main(void)
 {
-  struct vmstat_proc top[2];
   int i, loop_delay = 0, loop_max = 0;
   unsigned loop, rows = 25, page_kb = sysconf(_SC_PAGESIZE)/1024;
-  char *headers="r\0b\0swpd\0free\0buff\0cache\0si\0so\0bi\0bo\0in\0cs\0us\0"
-                "sy\0id\0wa", lengths[] = {2,2,7,7,6,7,5,5,5,5,5,5,2,2,2,2};
+  unsigned long long units, total_hz, *ptr, *oldptr;
+  char *headers = "r\0b\0swpd\0free\0buff\0cache\0si\0so\0bi\0bo\0in\0cs\0us\0"
+                  "sy\0id\0wa", lengths[] = {2,2,7,7,6,7,4,4,5,5,4,4,2,2,2,2};
 
-  memset(top, 0, sizeof(top));
   if (toys.optc) loop_delay = atolx_range(toys.optargs[0], 0, INT_MAX);
-  if (toys.optc > 1) loop_max = atolx_range(toys.optargs[1], 1, INT_MAX);
+  if (toys.optc>1) loop_max = atolx_range(toys.optargs[1], 1, INT_MAX);
 
-  for (loop = 0; !loop_max || loop < loop_max; loop++) {
-    unsigned idx = loop&1, offset = 0, expected = 0;
-    uint64_t units, total_hz, *ptr = (uint64_t *)(top+idx),
-             *oldptr = (uint64_t *)(top+!idx);
+  xreadfile("/proc/uptime", toybuf, sizeof(toybuf));
+  sscanf(toybuf, "%*s %llu", &units);
+
+  for (loop = 0; !loop_max || loop<loop_max; loop++) {
+    unsigned offset = 0, expected = 0;
 
     if (loop && loop_delay) sleep(loop_delay);
 
+    ptr = oldptr = (void *)toybuf;
+    *((loop&1) ? &ptr : &oldptr) += sizeof(struct vmstat_proc);
+    get_vmstat_proc((void *)ptr);
+
     // Print headers
     if (rows>3 && !(loop % (rows-3))) {
       char *header = headers;
 
-      if (!(toys.optflags&FLAG_n) && isatty(1)) terminal_size(0, &rows);
+      if (!FLAG(n) && isatty(1)) terminal_size(0, &rows);
       else rows = 0;
 
-      printf("procs ------------memory------------ ----swap--- -----io---- ---system-- ----cpu----\n");
-      for (i=0; i<sizeof(lengths); i++) {
+      printf("procs ------------memory------------ ---swap-- -----io---- --system- ----cpu----\n");
+      for (i = 0; i<sizeof(lengths); i++) {
         printf(" %*s"+!i, lengths[i], header);
         header += strlen(header)+1;
       }
       xputc('\n');
     }
 
-    // Read data and combine some fields we display as aggregates
-    get_vmstat_proc(top+idx);
-    top[idx].running--; // Don't include ourselves
-    top[idx].user += top[idx].nice;
-    top[idx].sys += top[idx].irq + top[idx].sirq;
-    top[idx].swaptotal -= top[idx].swapfree;
-
-    // Collect unit adjustments (outside the inner loop to save time)
-
-    if (!loop) {
-      char *s = toybuf;
-
-      xreadfile("/proc/uptime", toybuf, sizeof(toybuf));
-      while (*(s++) > ' ');
-      sscanf(s, "%"PRIu64, &units);
-    } else units = loop_delay;
+    if (loop) units = loop_delay;
 
     // add up user, sys, idle, and wait time used since last time
     // (Already appended nice to user)
-    total_hz = 0;
-    for (i=0; i<4; i++) total_hz += ptr[i+!!i] - oldptr[i+!!i];
+    for (i = total_hz = 0; i<4; i++) total_hz += ptr[i+!!i] - oldptr[i+!!i];
 
     // Output values in order[]: running, blocked, swaptotal, memfree, buffers,
-    // cache, swap_in, swap_out, io_in, io_out, sirq, ctxt, user, sys, idle,wait
+    // cache, swap_in, swap_out, io_in, io_out, intr, ctxt, user, sys, idle,wait
 
     for (i=0; i<sizeof(lengths); i++) {
-      char order[] = {9, 10, 15, 11, 12, 13, 18, 19, 16, 17, 6, 8, 0, 2, 3, 4};
-      uint64_t out = ptr[order[i]];
+      char order[] = {9, 10, 15, 11, 12, 13, 19, 20, 17, 18, 7, 8, 0, 2, 3, 4};
+      unsigned long long out = ptr[order[i]];
       int len;
 
       // Adjust rate and units
       if (i>5) out -= oldptr[order[i]];
       if (order[i]<7) out = ((out*100) + (total_hz/2)) / total_hz;
-      else if (order[i]>17) out = ((out * page_kb)+(units-1))/units;
-      else if (order[i]>15) out = ((out)+(units-1))/units;
-      else if (order[i]<9) out = (out+(units-1)) / units;
+      else if (order[i]>16) {
+        if (order[i]>18) out *= page_kb;
+        out = (out*page_kb+(units-1))/units;
+      } else if (order[i]<9) out = (out+(units-1)) / units;
 
       // If a field was too big to fit in its slot, try to compensate later
       expected += lengths[i] + !!i;
       len = expected - offset - !!i;
       if (len < 0) len = 0;
-      offset += printf(" %*"PRIu64+!i, len, out);
+      offset += printf(" %*llu"+!i, len, out);
     }
     xputc('\n');
 
diff --git a/toys/other/w.c b/toys/other/w.c
index a76c82f..c271e8b 100644
--- a/toys/other/w.c
+++ b/toys/other/w.c
@@ -7,7 +7,6 @@
 config W
   bool "w"
   default y
-  depends on TOYBOX_UTMPX
   help
     usage: w
 
diff --git a/toys/other/watchdog.c b/toys/other/watchdog.c
index 0402d3e..c3268a1 100644
--- a/toys/other/watchdog.c
+++ b/toys/other/watchdog.c
@@ -4,7 +4,7 @@
  *
  * See kernel.org/doc/Documentation/watchdog/watchdog-api.txt
 
-USE_WATCHDOG(NEWTOY(watchdog, "<1>1Ft#=4<1T#=60<1", TOYFLAG_NEEDROOT|TOYFLAG_BIN))
+USE_WATCHDOG(NEWTOY(watchdog, "<1>1Ft#=4<1T#=60<1", TOYFLAG_NEEDROOT|TOYFLAG_SBIN))
 
 config WATCHDOG
   bool "watchdog"
diff --git a/toys/other/xxd.c b/toys/other/xxd.c
index 3a070df..a37b0e3 100644
--- a/toys/other/xxd.c
+++ b/toys/other/xxd.c
@@ -10,25 +10,26 @@
  * xxd -p "plain" output:
  *   "4c696e75782076657273696f6e20342e392e302d342d616d643634202864"
 
-USE_XXD(NEWTOY(xxd, ">1c#<0>256l#o#g#<1=2iprs#[!rs]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_XXD(NEWTOY(xxd, ">1c#<0>256l#o#g#<0=2eiprs#[!rs][!re]", TOYFLAG_USR|TOYFLAG_BIN))
 
 config XXD
   bool "xxd"
   default y
   help
-    usage: xxd [-c n] [-g n] [-i] [-l n] [-o n] [-p] [-r] [-s n] [file]
+    usage: xxd [-eipr] [-cglos N] [file]
 
     Hexdump a file to stdout. If no file is listed, copy from stdin.
     Filename "-" is a synonym for stdin.
 
-    -c n	Show n bytes per line (default 16)
-    -g n	Group bytes by adding a ' ' every n bytes (default 2)
+    -c N	Show N bytes per line (default 16)
+    -e	Little-endian
+    -g N	Group bytes by adding a ' ' every N bytes (default 2)
     -i	Output include file (CSV hex bytes, plus C header/footer if not stdin)
-    -l n	Limit of n bytes before stopping (default is no limit)
-    -o n	Add n to display offset
-    -p	Plain hexdump (30 bytes/line, no grouping)
+    -l N	Limit of N bytes before stopping (default is no limit)
+    -o N	Add N to display offset
+    -p	Plain hexdump (30 bytes/line, no grouping. With -c 0 no wrap/group)
     -r	Reverse operation: turn a hexdump into a binary file
-    -s n	Skip to offset n
+    -s N	Skip to offset N
 */
 
 #define FOR_xxd
@@ -42,7 +43,7 @@
 {
   long long pos = 0;
   long long limit = TT.l;
-  int i, len, space;
+  int i, j, k, len, space, c = TT.c ? : sizeof(toybuf);
 
   if (FLAG(s)) {
     xlseek(fd, TT.s, SEEK_SET);
@@ -51,27 +52,39 @@
   }
 
   while (0<(len = readall(fd, toybuf,
-                          (limit && limit-pos<TT.c)?limit-pos:TT.c)))
+                          (limit && limit-pos<c)?limit-pos:c)))
   {
     if (!FLAG(p)) printf("%08llx: ", TT.o + pos);
     pos += len;
-    space = 2*TT.c+TT.c/TT.g+1;
+    space = 2*TT.c;
+    space += TT.g ? (TT.c+TT.g-1)/TT.g+1 : 2;
 
-    for (i=0; i<len;) {
-      space -= printf("%02x", toybuf[i]);
-      if (!(++i%TT.g)) {
+    for (i=0, j=1; i<len; ) {
+      // Insert padding for short groups in little-endian mode.
+      if (FLAG(e) && j==1 && (len-i)<TT.g) {
+        for (k=0; k<(TT.g-(len-i)); k++) {
+          space -= printf("  ");
+          j++;
+        }
+      }
+
+      space -= printf("%02x", toybuf[FLAG(e) ? (i + TT.g - j) : i]);
+      i++,j+=2;
+      if (TT.g && !(i%TT.g)) {
         putchar(' ');
         space--;
+        j=1;
       }
     }
 
     if (!FLAG(p)) {
       printf("%*s", space, "");
-      for (i=0; i<len; i++)
+      for (i = 0; i<len; i++)
         putchar((toybuf[i]>=' ' && toybuf[i]<='~') ? toybuf[i] : '.');
     }
-    putchar('\n');
+    if (TT.c || !FLAG(p)) putchar('\n');
   }
+  if (!TT.c && FLAG(p)) putchar('\n');
   if (len<0) perror_exit("read");
 }
 
@@ -104,7 +117,8 @@
 
 static void do_xxd_reverse(int fd, char *name)
 {
-  FILE *fp = xfdopen(fd, "r");
+  FILE *fp = xfdopen(xdup(fd), "r");
+  long long pos, current_pos = 0;
   int tmp;
 
   // -ri is a very easy special case.
@@ -114,21 +128,17 @@
 
     // Each line of a regular hexdump starts with an offset/address.
     // Each line of a plain hexdump just goes straight into the bytes.
-    if (!FLAG(p)) {
-      long long pos;
-
-      if (fscanf(fp, "%llx: ", &pos) == 1) {
-        if (fseek(stdout, pos, SEEK_SET) != 0) {
-          // TODO: just write out zeros if non-seekable?
-          perror_exit("%s: seek failed", name);
-        }
+    if (!FLAG(p) && fscanf(fp, "%llx: ", &pos) == 1) {
+      if (pos != current_pos && fseek(stdout, pos, SEEK_SET)) {
+        // TODO: just write out zeros if non-seekable?
+        perror_exit("%s: seek failed", name);
       }
     }
 
     // A plain hexdump can have as many bytes per line as you like,
     // but a non-plain hexdump assumes garbage after it's seen the
     // specified number of bytes.
-    while (FLAG(p) || col < TT.c) {
+    while (FLAG(p) || !TT.c || col < TT.c) {
       int n1, n2;
 
       // If we're at EOF or EOL or we read some non-hex...
@@ -141,6 +151,7 @@
 
       fputc((n1 << 4) | (n2 & 0xf), stdout);
       col++;
+      current_pos++;
 
       // Is there any grouping going on? Ignore a single space.
       tmp = fgetc(fp);
@@ -157,10 +168,10 @@
 
 void xxd_main(void)
 {
-  if (!TT.c) TT.c = FLAG(i) ? 12 : 16;
-
   // Plain style is 30 bytes/line, no grouping.
-  if (FLAG(p)) TT.c = TT.g = 30;
+  if (!FLAG(c)) TT.c = FLAG(p) ? 30 : FLAG(i) ? 12 : 16;
+  if (FLAG(e) && !FLAG(g)) TT.g = 4;
+  if (FLAG(p) && !FLAG(g)) TT.g = TT.c;
 
   loopfiles(toys.optargs,
     FLAG(r) ? do_xxd_reverse : (FLAG(i) ? do_xxd_include : do_xxd));
diff --git a/toys/pending/bc.c b/toys/pending/bc.c
index 3713140..1288fab 100644
--- a/toys/pending/bc.c
+++ b/toys/pending/bc.c
@@ -5370,7 +5370,7 @@
   id.len = p->fns.len;
 
   new = bc_map_insert(&p->fn_map, &id, &idx);
-  idx = ((struct ptr_len *)bc_vec_item(&p->fn_map, idx))->len;
+  idx = ((struct BcVec *)bc_vec_item(&p->fn_map, idx))->len;
 
   if (!new) {
     BcFunc *func = bc_vec_item(&p->fns, idx);
diff --git a/toys/pending/bootchartd.c b/toys/pending/bootchartd.c
index 7808428..49be5c4 100644
--- a/toys/pending/bootchartd.c
+++ b/toys/pending/bootchartd.c
@@ -14,11 +14,11 @@
   help
     usage: bootchartd {start [PROG ARGS]}|stop|init
 
-    Create /var/log/bootlog.tgz with boot chart data
+    Record boot chart data into /var/log/bootlog.tgz
 
     start: start background logging; with PROG, run PROG,
-           then kill logging with USR1
-    stop:  send USR1 to all bootchartd processes
+           then kill logging with SIGUSR1
+    stop:  send SIGUSR1 to all bootchartd processes
     init:  start background logging; stop when getty/xdm is seen
           (for init scripts)
 
@@ -71,18 +71,18 @@
         xclose(fd);
         continue;
       }
-      toybuf[len] = '\0';
+      toybuf[len] = 0;
       close(fd);
       fputs(toybuf, fp);
       if (TT.pid != 1) continue;
       if ((ptr = strchr(toybuf, '('))) {
         char *tmp = strchr(++ptr, ')');
 
-        if (tmp) *tmp = '\0';
+        if (tmp) *tmp = 0;
       }
       // Checks for gdm, kdm or getty
-      if (((ptr[0] == 'g' || ptr[0] == 'k' || ptr[0] == 'x') && ptr[1] == 'd'
-            && ptr[2] == 'm') || strstr(ptr, "getty")) login_flag = 1;
+      if ((strchr("gkx", *ptr) && ptr[1] == 'd' && ptr[2] == 'm')
+        || strstr(ptr, "getty")) login_flag = 1;
     }
   }
   closedir(proc_dir);
@@ -103,16 +103,15 @@
     while (*ptr == ' ' || *ptr == '\t') ptr++;
     if (!*ptr || *ptr == '#' || *ptr == '\n') continue;
     if (strstart(&ptr, "SAMPLE_PERIOD=")) {
-      double dd;
-
-      sscanf(ptr, "%lf", &dd);
-      if ((TT.msec = dd*1000)<1) TT.msec = 1;
+      TT.msec = xparsemillitime(ptr);
+      if (TT.msec<1) TT.msec = 1;
     } else if (strstart(&ptr, "PROCESS_ACCOUNTING="))
       if (strstart(&ptr, "\"on\"") || strstart(&ptr, "\"yes\""))
         TT.proc_accounting = 1;
     free(line);
   }
   fclose(fp);
+
   return 1;
 }
 
@@ -123,46 +122,44 @@
 
   if ((dir = mkdtemp(dir_path))) {
     xchdir((dir = xstrdup(dir)));
+
     return dir;
   }
   while (mount("none", *target, "tmpfs", (1<<15), "size=16m")) //MS_SILENT
     if (!++target) perror_exit("can't mount tmpfs");
   xchdir(*target);
   if (umount2(*target, MNT_DETACH)) perror_exit("Can't unmount tmpfs");
+
   return *target;
 }
 
 static void start_logging()
 {
   struct timespec ts;
-  int proc_stat_fd = xcreate("proc_stat.log",  
-      O_WRONLY | O_CREAT | O_TRUNC, 0644);
-  int proc_diskstats_fd = xcreate("proc_diskstats.log",  
-      O_WRONLY | O_CREAT | O_TRUNC, 0644);
+  int sfd = xcreate("proc_stat.log",  O_WRONLY|O_CREAT|O_TRUNC, 0644),
+      dfd = xcreate("proc_diskstats.log",  O_WRONLY|O_CREAT|O_TRUNC, 0644);
   FILE *proc_ps_fp = xfopen("proc_ps.log", "w");
   long tcnt = 60 * 1000 / TT.msec;
 
   if (tcnt <= 0) tcnt = 1;
   if (TT.proc_accounting) {
-    int kp_fd = xcreate("kernel_procs_acct", O_WRONLY | O_CREAT | O_TRUNC,0666);
-
-    xclose(kp_fd);
+    xclose(xcreate("kernel_procs_acct", O_WRONLY|O_CREAT|O_TRUNC, 0666));
     acct("kernel_procs_acct");
   }
   while (--tcnt && !toys.signal) {
     clock_gettime(CLOCK_BOOTTIME, &ts);
     sprintf(TT.timestamp, "%ld.%02d\n", (long) ts.tv_sec,
         (int) (ts.tv_nsec/10000000));
-    dump_data_in_file("/proc/stat", proc_stat_fd);
-    dump_data_in_file("/proc/diskstats", proc_diskstats_fd);
+    dump_data_in_file("/proc/stat", sfd);
+    dump_data_in_file("/proc/diskstats", dfd);
     // stop proc dumping in 2 secs if getty or gdm, kdm, xdm found 
     if (dump_proc_data(proc_ps_fp))
       if (tcnt > 2 * 1000 / TT.msec) tcnt = 2 * 1000 / TT.msec;
     fflush(0);
     msleep(TT.msec);
   }
-  xclose(proc_stat_fd);
-  xclose(proc_diskstats_fd);
+  xclose(sfd);
+  xclose(dfd);
   fclose(proc_ps_fp);
 }
 
@@ -204,6 +201,8 @@
   snprintf(toybuf, sizeof(toybuf), "tar -zcf /var/log/bootlog.tgz header %s *.log", 
       TT.proc_accounting ? "kernel_procs_acct" : "");
   system(toybuf);
+
+  // We created a tmpdir then lazy unmounted it, why are we deleting files...?
   if (tmp_dir) {
     unlink("header");
     unlink("proc_stat.log");
diff --git a/toys/pending/brctl.c b/toys/pending/brctl.c
index 6017851..c007618 100644
--- a/toys/pending/brctl.c
+++ b/toys/pending/brctl.c
@@ -143,12 +143,12 @@
   unsigned long args[4] = {BRCTL_ADD_IF, 0, 0, 0};
 
   if (!(index = if_nametoindex(argv[1]))) perror_exit("interface %s", argv[1]);
+  xstrncpy(ifr.ifr_name, argv[0], IFNAMSIZ);
 #ifdef SIOCBRADDIF
   ifr.ifr_ifindex = index;
   xioctl(TT.sockfd, SIOCBRADDIF, &ifr);
 #else
   args[1] = index;
-  xstrncpy(ifr.ifr_name, argv[0], IFNAMSIZ);
   ifr.ifr_data = (char *)args;
   xioctl(TT.sockfd, SIOCDEVPRIVATE, &ifr);
 #endif
@@ -161,12 +161,12 @@
   unsigned long args[4] = {BRCTL_DEL_IF, 0, 0, 0};
 
   if (!(index = if_nametoindex(argv[1]))) perror_exit("interface %s",argv[1]);
+  xstrncpy(ifr.ifr_name, argv[0], IFNAMSIZ);
 #ifdef SIOCBRDELIF
-  ifr.ifr_ifindex = ifindex;
+  ifr.ifr_ifindex = index;
   xioctl(TT.sockfd, SIOCBRDELIF, &ifr);
 #else
   args[1] = index;     
-  xstrncpy(ifr.ifr_name, argv[0], IFNAMSIZ);
   ifr.ifr_data = (char *)args;  
   xioctl(TT.sockfd, SIOCDEVPRIVATE, &ifr);
 #endif
diff --git a/toys/pending/dd.c b/toys/pending/dd.c
index 199e591..9a4d6df 100644
--- a/toys/pending/dd.c
+++ b/toys/pending/dd.c
@@ -1,9 +1,9 @@
-/* dd.c - program to convert and copy a file.
+/* dd.c - convert/copy a file
  *
  * Copyright 2013 Ashwini Kumar <ak.ashwini@gmail.com>
  * Copyright 2013 Kyungwan Han <asura321@gmail.com>
  *
- * See  http://opengroup.org/onlinepubs/9699919799/utilities/dd.html
+ * See http://opengroup.org/onlinepubs/9699919799/utilities/dd.html
 
 USE_DD(NEWTOY(dd, 0, TOYFLAG_USR|TOYFLAG_BIN))
 
@@ -11,37 +11,28 @@
   bool "dd"
   default n
   help
-    usage: dd [if=FILE] [of=FILE] [ibs=N] [obs=N] [iflag=FLAGS] [oflag=FLAGS]
-            [bs=N] [count=N] [seek=N] [skip=N]
-            [conv=notrunc|noerror|sync|fsync] [status=noxfer|none]
+    usage: dd [if|of=FILE] [ibs|obs|bs|count|seek|skip=N] [conv|status|iflag|oflag=FLAG[,FLAG...]]
 
-    Copy/convert files.
+    Copy/convert blocks of data from input to output, with the following
+    keyword=value modifiers (and their default values):
 
-    if=FILE		Read from FILE instead of stdin
-    of=FILE		Write to FILE instead of stdout
-    bs=N		Read and write N bytes at a time
-    ibs=N		Input block size
-    obs=N		Output block size
-    count=N		Copy only N input blocks
-    skip=N		Skip N input blocks
-    seek=N		Skip N output blocks
-    iflag=FLAGS	Set input flags
-    oflag=FLAGS	Set output flags
-    conv=notrunc	Don't truncate output file
-    conv=noerror	Continue after read errors
-    conv=sync	Pad blocks with zeros
-    conv=fsync	Physically write data out before finishing
-    status=noxfer	Don't show transfer rate
-    status=none	Don't show transfer rate or records in/out
+    if=FILE  Read FILE (stdin)          of=FILE  Write to FILE (stdout)
+       bs=N  Block size in bytes (512)  count=N  Stop after copying N blocks
+      ibs=N  Input block size (bs=)       obs=N  Output block size (bs=)
+     skip=N  Skip N input blocks (0)     seek=N  Skip N output blocks (0)
 
-    FLAGS is a comma-separated list of:
+    Each =N value accepts the normal unit suffixes (see toybox --help).
 
-    count_bytes	(iflag) interpret count=N in bytes, not blocks
-    seek_bytes	(oflag) interpret seek=N in bytes, not blocks
-    skip_bytes	(iflag) interpret skip=N in bytes, not blocks
+    These modifiers take a comma separated list of potential options:
 
-    Numbers may be suffixed by c (*1), w (*2), b (*512), kD (*1000), k (*1024),
-    MD (*1000*1000), M (*1024*1024), GD (*1000*1000*1000) or G (*1024*1024*1024).
+    iflag=count_bytes,skip_bytes   count=N or skip=N is in bytes not blocks
+    oflag=seek_bytes,append        seek=N is in bytes, append output to file
+    status=noxfer,none             don't show transfer rate, no summary info
+    conv=
+      notrunc  Don't truncate output    noerror  Continue after read errors
+      sync     Zero pad short reads     fsync    Flush output to disk at end
+      sparse   Seek past zeroed output  excl     Fail if output file exists
+      nocreat  Fail if of=FILE missing
 */
 
 #define FOR_dd
@@ -49,8 +40,7 @@
 
 GLOBALS(
   int show_xfer, show_records;
-  unsigned long long bytes, c_count, in_full, in_part, out_full, out_part;
-  struct timeval start;
+  unsigned long long bytes, in_full, in_part, out_full, out_part, start;
   struct {
     char *name;
     int fd;
@@ -66,7 +56,7 @@
 };
 
 static const struct dd_flag dd_conv[] = TAGGED_ARRAY(DD_conv,
-  {"fsync"}, {"noerror"}, {"notrunc"}, {"sync"},
+  {"fsync"}, {"noerror"}, {"notrunc"}, {"sync"}, // TODO sparse excl nocreat
 );
 
 static const struct dd_flag dd_iflag[] = TAGGED_ARRAY(DD_iflag,
@@ -79,12 +69,7 @@
 
 static void status()
 {
-  double seconds;
-  struct timeval now;
-
-  gettimeofday(&now, NULL);
-  seconds = ((now.tv_sec * 1000000 + now.tv_usec) -
-      (TT.start.tv_sec * 1000000 + TT.start.tv_usec))/1000000.0;
+  unsigned long long now = millitime()-TT.start ? : 1, bytes = TT.bytes*1000;
 
   if (TT.show_records)
     fprintf(stderr, "%llu+%llu records in\n%llu+%llu records out\n",
@@ -93,17 +78,12 @@
   if (TT.show_xfer) {
     human_readable(toybuf, TT.bytes, HR_SPACE|HR_B);
     fprintf(stderr, "%llu bytes (%s) copied, ", TT.bytes, toybuf);
-    human_readable(toybuf, TT.bytes/seconds, HR_SPACE|HR_B);
-    fprintf(stderr, "%f s, %s/s\n", seconds, toybuf);
+    bytes = (bytes>TT.bytes) ? bytes/now : TT.bytes/((now+999)/1000);
+    human_readable(toybuf, bytes, HR_SPACE|HR_B);
+    fprintf(stderr, "%llu.%03u s, %s/s\n", now/1000, (int)(now%1000), toybuf);
   }
 }
 
-static void dd_sigint(int sig)
-{
-  toys.exitval = sig|128;
-  xexit();
-}
-
 static void write_out(int all)
 {
   TT.out.bp = TT.out.buff;
@@ -128,31 +108,26 @@
   char *pre = xstrdup(arg);
   int i;
 
-  for (i=0; i<flag_count; ++i) {
+  for (i = 0; i<flag_count; ++i)
     while (comma_remove(pre, flags[i].name)) *result |= 1<<i;
-  }
   if (*pre) error_exit("bad %s=%s", what, pre);
   free(pre);
 }
 
 void dd_main()
 {
-  char **args;
-  unsigned long long bs = 0;
+  char **args, *arg;
+  unsigned long long bs = 0, count = ULLONG_MAX;
   int trunc = O_TRUNC;
 
   TT.show_xfer = TT.show_records = 1;
-  TT.c_count = ULLONG_MAX;
 
   TT.in.sz = TT.out.sz = 512; //default io block size
-  for (args = toys.optargs; *args; args++) {
-    char *arg = *args;
-
+  for (args = toys.optargs; (arg = *args); args++) {
     if (strstart(&arg, "bs=")) bs = atolx_range(arg, 1, LONG_MAX);
     else if (strstart(&arg, "ibs=")) TT.in.sz = atolx_range(arg, 1, LONG_MAX);
     else if (strstart(&arg, "obs=")) TT.out.sz = atolx_range(arg, 1, LONG_MAX);
-    else if (strstart(&arg, "count="))
-      TT.c_count = atolx_range(arg, 0, LLONG_MAX);
+    else if (strstart(&arg, "count=")) count = atolx_range(arg, 0, LLONG_MAX);
     else if (strstart(&arg, "if=")) TT.in.name = arg;
     else if (strstart(&arg, "of=")) TT.out.name = arg;
     else if (strstart(&arg, "seek="))
@@ -163,10 +138,9 @@
       if (!strcmp(arg, "noxfer")) TT.show_xfer = 0;
       else if (!strcmp(arg, "none")) TT.show_xfer = TT.show_records = 0;
       else error_exit("unknown status '%s'", arg);
-    } else if (strstart(&arg, "conv=")) {
+    } else if (strstart(&arg, "conv="))
       parse_flags("conv", arg, dd_conv, ARRAY_LEN(dd_conv), &TT.conv);
-      fprintf(stderr, "conv=%x\n", TT.conv);
-    } else if (strstart(&arg, "iflag="))
+    else if (strstart(&arg, "iflag="))
       parse_flags("iflag", arg, dd_iflag, ARRAY_LEN(dd_iflag), &TT.iflag);
     else if (strstart(&arg, "oflag="))
       parse_flags("oflag", arg, dd_oflag, ARRAY_LEN(dd_oflag), &TT.oflag);
@@ -175,9 +149,8 @@
   if (bs) TT.in.sz = TT.out.sz = bs;
 
   sigatexit(status);
-  xsignal(SIGINT, dd_sigint);
   xsignal(SIGUSR1, status);
-  gettimeofday(&TT.start, NULL);
+  TT.start = millitime();
 
   // For bs=, in/out is done as it is. so only in.sz is enough.
   // With Single buffer there will be overflow in a read following partial read.
@@ -219,8 +192,7 @@
   }
 
   // Implement seek= and truncate as necessary. We handled position zero
-  // truncate with O_TRUNC on open, so output to /dev/null and such doesn't
-  // error.
+  // truncate with O_TRUNC on open, so output to /dev/null etc doesn't error.
   bs = TT.out.offset;
   if (!(TT.oflag & _DD_oflag_seek_bytes)) bs *= TT.out.sz;
   if (bs) {
@@ -228,19 +200,19 @@
 
     xlseek(TT.out.fd, bs, SEEK_CUR);
     if (trunc && !fstat(TT.out.fd, &st) && S_ISREG(st.st_mode)
-      && ftruncate(TT.out.fd, bs)) perror_exit("unexpected ftruncate failure");
+      && ftruncate(TT.out.fd, bs)) perror_exit("truncate");
   }
 
-  unsigned long long bytes_left = TT.c_count;
-  if (TT.c_count != ULLONG_MAX && !(TT.iflag & _DD_iflag_count_bytes)) {
-    bytes_left *= TT.in.sz;
-  }
-  while (bytes_left) {
-    int chunk = bytes_left < TT.in.sz ? bytes_left : TT.in.sz;
+  if (!(TT.iflag & _DD_iflag_count_bytes) && count*TT.in.sz>count)
+    count *= TT.in.sz;
+
+  while (count) {
+    int chunk = minof(count, TT.in.sz);
     ssize_t n;
 
     TT.in.bp = TT.in.buff + TT.in.count;
     if (TT.conv & _DD_conv_sync) memset(TT.in.bp, 0, TT.in.sz);
+    errno = 0;
     if (!(n = read(TT.in.fd, TT.in.bp, chunk))) break;
     if (n < 0) {
       if (errno == EINTR) continue;
@@ -261,7 +233,7 @@
       if (TT.conv & _DD_conv_sync) TT.in.count += TT.in.sz;
       else TT.in.count += n;
     }
-    bytes_left -= n;
+    count -= n;
 
     TT.out.count = TT.in.count;
     if (bs) {
diff --git a/toys/pending/diff.c b/toys/pending/diff.c
index 4dd0165..f12b4a3 100644
--- a/toys/pending/diff.c
+++ b/toys/pending/diff.c
@@ -3,53 +3,67 @@
  * Copyright 2014 Sandeep Sharma <sandeep.jack2756@gmail.com>
  * Copyright 2014 Ashwini Kumar <ak.ashwini1981@gmail.com>
  *
- * See: http://cm.bell-labs.com/cm/cs/cstr/41.pdf
+ * See https://pubs.opengroup.org/onlinepubs/9699919799/utilities/diff.html
+ * and https://www.cs.dartmouth.edu/~doug/diff.pdf
+ *
+ * Deviations from posix: always does -u
 
-USE_DIFF(NEWTOY(diff, "<2>2(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)L(label)*S(starting-file):N(new-file)r(recursive)U(unified)#<0=3", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
+USE_DIFF(NEWTOY(diff, "<2>2(unchanged-line-format):;(old-line-format):;(new-line-format):;(color)(strip-trailing-cr)B(ignore-blank-lines)d(minimal)b(ignore-space-change)ut(expand-tabs)w(ignore-all-space)i(ignore-case)T(initial-tab)s(report-identical-files)q(brief)a(text)S(starting-file):F(show-function-line):;L(label)*N(new-file)r(recursive)U(unified)#<0=3", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
 
 config DIFF
   bool "diff"
   default n
   help
-  usage: diff [-abBdiNqrTstw] [-L LABEL] [-S FILE] [-U LINES] FILE1 FILE2
+  usage: diff [-abBdiNqrTstw] [-L LABEL] [-S FILE] [-U LINES] [-F REGEX ] FILE1 FILE2
 
   -a	Treat all files as text
   -b	Ignore changes in the amount of whitespace
   -B	Ignore changes whose lines are all blank
   -d	Try hard to find a smaller set of changes
+  -F 	Show the most recent line matching the regex
   -i	Ignore case differences
   -L	Use LABEL instead of the filename in the unified header
   -N	Treat absent files as empty
   -q	Output only whether files differ
   -r	Recurse
   -S	Start with FILE when comparing directories
-  -T	Make tabs line up by prefixing a tab when necessary
   -s	Report when two files are the same
+  -T	Make tabs line up by prefixing a tab when necessary
   -t	Expand tabs to spaces in output
   -u	Unified diff
   -U	Output LINES lines of context
   -w	Ignore all whitespace
 
-  --color              Colored output
-  --strip-trailing-cr  Strip trailing '\r's from input lines
+  --color     Color output   --strip-trailing-cr   Strip '\r' from input lines
+  --TYPE-line-format=FORMAT  Display TYPE (unchanged/old/new) lines using FORMAT
+    FORMAT uses printf integer escapes (ala %-2.4x) followed by LETTER: FELMNn
+  Supported format specifiers are:
+  * %l, the contents of the line, without the trailing newline
+  * %L, the contents of the line, including the trailing newline
+  * %%, the character '%'
 */
 
 #define FOR_diff
 #include "toys.h"
 
 GLOBALS(
-  long ct;
-  char *start;
-  struct arg_list *L_list;
+  long U;
+  struct arg_list *L;
+  char *F, *S, *new_line_format, *old_line_format, *unchanged_line_format;
 
-  int dir_num, size, is_binary, status, change, len[2];
-  int *offset[2];
+  int dir_num, size, is_binary, differ, change, len[2], *offset[2];
   struct stat st[2];
+  struct {
+    char **list;
+    int nr_elm;
+  } dir[2];
+  struct {
+    FILE *fp;
+    int len;
+  } file[2];
 )
 
-#define MIN(x,y) ((x) < (y) ? (x) : (y))
-#define MAX(x,y) ((x) > (y) ? (x) : (y))
-#define IS_STDIN(s)     ((s)[0] == '-' && !(s)[1])
+#define IS_STDIN(s)     (*(s)=='-' && !(s)[1])
 
 struct v_vector {
   unsigned serial:31;
@@ -64,24 +78,9 @@
   long a, b, c, d, prev, suff;
 };
 
-static struct dir_t {
-  char **list;
-  int nr_elm;
-} dir[2];
-
 struct candidate {
+  struct candidate *next, *prev;
   int a, b;
-  struct candidate *prev, *next;
-};
-
-static struct file_t {
-  FILE *fp;
-  int len;
-} file[2];
-
-enum {
-  SAME,
-  DIFFER,
 };
 
 enum {
@@ -91,36 +90,27 @@
   space = 1 << 12
 };
 
-static int comp(const void *a, const void* b)
+static int comp(void *a, void *b)
 {
-  int i = ((struct v_vector *)a)->hash -
-    ((struct v_vector *)b)->hash;
+  int i = ((struct v_vector *)a)->hash - ((struct v_vector *)b)->hash;
 
-  if (!i) i = ((struct v_vector *)a)->serial -
-    ((struct v_vector *)b)->serial;
-  return i;
+  return i ? : ((struct v_vector *)a)->serial - ((struct v_vector *)b)->serial;
 }
 
-static int search (struct candidate **K, int r, int k, int j)
+static int search(struct candidate **K, int r, int k, int j)
 {
   int low = r, upper = k, mid;
 
-  mid = (low + upper) / 2;
-  while (low <= mid) {
-    if (((struct candidate*)(K[mid]))->b < j &&
-        ((struct candidate*)(K[mid + 1]))->b > j)
-      return mid;
-
-    if (((struct candidate*)(K[mid]))->b < j) low = mid + 1;
-    else if (((struct candidate*)(K[mid]))->b > j) upper = mid - 1;
+  while (low<=(mid = (low+upper)/2)) {
+    if (K[mid]->b < j && K[mid + 1]->b > j) return mid;
+    if (K[mid]->b < j) low = mid + 1;
+    else if (K[mid]->b > j) upper = mid - 1;
     else return -1;
-
-    mid = (low + upper) / 2;
   }
   return -1;
 }
 
-static struct candidate * new_candidate (int i, int j, struct candidate* prev)
+static struct candidate *new_candidate(int i, int j, struct candidate *prev)
 {
   struct candidate *c = xzalloc(sizeof(struct candidate));
 
@@ -130,18 +120,7 @@
   return c;
 }
 
-
-static void free_candidates(struct candidate *c)
-{
-  struct candidate *t = c;
-  
-  while ((t = c)) {
-    c = c->next;
-    free(t);
-  }
-}
-/*
- * 1. Search K[r: k] for an element K[s] such that K[s]-> b < j and K[s + 1]->b > j
+/* 1. Search K[r: k] for an element K[s] such that K[s]-> b < j and K[s + 1]->b > j
  * 2. if found do
  *  2.a. If K[s + 1]->b > j do K[r] = c; r = s+1 and c = candidate(i, j, K[s]) //we have a candidate
  *  2.b. if s = k (fence reached move it further) do K[k + 2] = K[k + 1], k++
@@ -149,49 +128,35 @@
  *    else p = p + 1 //keep traversing the equiv class.
  * 4. K[r] = c //Save the sucessfully filled k-candidate.
  */
-static void  do_merge(struct candidate **K, int *k, int i,
+static void do_merge(struct candidate **K, int *k, int i,
     struct v_vector *E, int p)
 {
   int r = 0, s, j;
   struct candidate *pr = 0, *c = K[0];
 
-  while (1) {
+  for (;;) {
     j = E[p].serial;
     s = search(K, r, *k, j);
-    if (s >= 0 && (((struct candidate*)(K[s]))->b < j &&
-          ((struct candidate*)(K[s + 1]))->b > j)) {
-
-      if (((struct candidate*)(K[s + 1]))->b > j) {
+    if (s>=0 && K[s]->b<j && K[s+1]->b>j) {
+      if (K[s+1]->b>j) {
         pr = K[s];
         if (r && K[r]) c->next = K[r];
         K[r] = c;
-        r = s + 1;
+        r = s+1;
         c = new_candidate(i , j, pr);
       }
       if (s == *k) {
-        K[*k + 2] = K[*k + 1];
-        *k = *k + 1;
+        ++*k;
+        K[*k+1] = K[*k];
         break;
       }
     }
     if (E[p].last) break;
-    else p = p + 1;
+    else p++;
   }
   K[r] = c;
 }
 
-static FILE* read_stdin()
-{
-  char *tmp_name;
-  int tmpfd = xtempfile("stdin", &tmp_name);
-
-  unlink(tmp_name);
-  free(tmp_name);
-
-  xsendfile(0, tmpfd);
-  return fdopen(tmpfd, "r");
-}
-
 static int read_tok(FILE *fp, off_t *off, int tok)
 {
   int t = 0, is_space;
@@ -215,12 +180,11 @@
     tok |= (t & (eof + eol)); //set tok eof+eol when t is eof
 
     if (t == '\n') tok |= eol;
-    if (toys.optflags & FLAG_i)
-      if (t >= 'A' && t <= 'Z') t = tolower(t);
+    if (FLAG(i)) if (t >= 'A' && t <= 'Z') t = tolower(t);
 
-    if (toys.optflags & FLAG_w && is_space) continue;
+    if (FLAG(w) && is_space) continue;
 
-    if (toys.optflags & FLAG_b) {
+    if (FLAG(b)) {
       if (tok & space) {
         if (is_space) continue;
         tok &= ~space;
@@ -234,18 +198,13 @@
   return tok;
 }
 
-int bcomp(const void *a, const void *b) 
+int bcomp(void *a, void *b)
 {
-  struct v_vector *l = (struct v_vector*)a,
-                  *r = (struct v_vector*)b;
-  int ret = l->hash - r->hash;
+  struct v_vector *l = (struct v_vector *)a, *r = (struct v_vector *)b;
 
-  if (!ret) {
-    if ((r -1)->last) return 0;
-    else return -1;
-  }
-  return ret;
+  return (l->hash-r->hash) ? : r[-1].last ? 0 : -1;
 }
+
 /*  file[0] corresponds file 1 and file[1] correspond file 2.
  * 1. calc hashes for both the files and store them in vector(v[0], v[1])
  * 2. sort file[1] with hash as primary and serial as sec. key
@@ -259,7 +218,7 @@
  * 6. Create a vector J[i] = j, such that i'th line in file[0] is j'th line of
  *    file[1], i.e J comprises LCS
  */
-static int * create_j_vector()
+static int *create_j_vector()
 {
   int tok, i, j, size = 100, k;
   off_t off;
@@ -273,96 +232,92 @@
     hash = 5831;
     v[i] = xzalloc(size * sizeof(struct v_vector));
     TT.offset[i] = xzalloc(size * sizeof(int));
-    file[i].len = 0;
-    fseek(file[i].fp, 0, SEEK_SET);
+    TT.file[i].len = 0;
+    if (fseek(TT.file[i].fp, 0, SEEK_SET)) perror_exit("fseek failed");
 
     while (1) {
-      tok  = read_tok(file[i].fp, &off, tok);
+      tok  = read_tok(TT.file[i].fp, &off, tok);
       if (!(tok & empty)) {
         hash = ((hash << 5) + hash) + (tok & 0xff);
         continue;
       }
 
-      if (size == ++file[i].len) {
+      if (size == ++TT.file[i].len) {
         size = size * 11 / 10;
         v[i] = xrealloc(v[i], size*sizeof(struct v_vector));
         TT.offset[i] = xrealloc(TT.offset[i], size*sizeof(int));
       }
 
-      v[i][file[i].len].hash = hash & INT_MAX;
-      TT.offset[i][file[i].len] = off;
+      v[i][TT.file[i].len].hash = hash & INT_MAX;
+      TT.offset[i][TT.file[i].len] = off;
       if ((tok & eof)) {
-        TT.offset[i][file[i].len] = ++off;
+        TT.offset[i][TT.file[i].len] = ++off;
         break;
       }
       hash = 5831;  //next line
       tok = 0;
     }
-    if (TT.offset[i][file[i].len] - TT.offset[i][file[i].len - 1] == 1)
-      file[i].len--;
+    if (TT.offset[i][TT.file[i].len]-TT.offset[i][TT.file[i].len-1] == 1)
+      TT.file[i].len--;
   }
 
-  for (i = 0; i <= file[1].len; i++) v[1][i].serial = i;
-  qsort(v[1] + 1, file[1].len, sizeof(struct v_vector), comp);
+  for (i = 0; i<=TT.file[1].len; i++) v[1][i].serial = i;
+  qsort(v[1]+1, TT.file[1].len, sizeof(struct v_vector), (void *)comp);
 
   e = v[1];
   e[0].serial = 0;
   e[0].last = 1;
-  for ( i = 1; i <= file[1].len; i++) {
-    if ((i == file[1].len) || (v[1][i].hash != v[1][i+1].hash)) e[i].last = 1;
-    else e[i].last = 0;
+  for (i = 1; i<=TT.file[1].len; i++)
+    e[i].last = i==TT.file[1].len || v[1][i].hash!=v[1][i+1].hash;
+
+  p_vector = xzalloc((TT.file[0].len+2)*sizeof(int));
+  for (i = 1; i<=TT.file[0].len; i++) {
+    void *r = bsearch(&v[0][i], e+1, TT.file[1].len, sizeof(*e), (void *)bcomp);
+    if (r) p_vector[i] = (struct v_vector *)r - e;
   }
 
-  p_vector = xzalloc((file[0].len + 2) * sizeof(int));
-  for (i = 1; i <= file[0].len; i++) {
-    void *r = bsearch(&v[0][i], (e + 1), file[1].len, sizeof(e[0]), bcomp);
-    if (r) p_vector[i] = (struct v_vector*)r - e;
-  }
-
-  for (i = 1; i <= file[0].len; i++)
-    e[i].p = p_vector[i];
+  for (i = 1; i<=TT.file[0].len; i++) e[i].p = p_vector[i];
   free(p_vector);
 
   size = 100;
-  kcand = xzalloc(size * sizeof(struct candidate*));
+  kcand = xzalloc(size * sizeof(struct candidate *));
 
-  kcand[0] = new_candidate(0 , 0, NULL);
-  kcand[1] = new_candidate(file[0].len+1, file[1].len+1, NULL); //the fence
+  kcand[0] = new_candidate(0 , 0, 0);
+  kcand[1] = new_candidate(TT.file[0].len+1, TT.file[1].len+1, 0); //the fence
 
   k = 0;  //last successfully filled k candidate.
-  for (i = 1; i <= file[0].len; i++) {
-
+  for (i = 1; i<=TT.file[0].len; i++) {
     if (!e[i].p) continue;
     if ((size - 2) == k) {
       size = size * 11 / 10;
-      kcand = xrealloc(kcand, (size * sizeof(struct candidate*)));
+      kcand = xrealloc(kcand, (size*sizeof(struct candidate *)));
     }
     do_merge(kcand, &k, i, e, e[i].p);
   }
   free(v[0]); //no need for v_vector now.
   free(v[1]);
 
-  J = xzalloc((file[0].len + 2) * sizeof(int));
+  J = xzalloc((TT.file[0].len+2)*sizeof(int));
 
-  for (pr = kcand[k]; pr; pr = pr->prev)
-    J[pr->a] = pr->b;
-  J[file[0].len + 1] = file[1].len+1; //mark boundary
+  for (pr = kcand[k]; pr; pr = pr->prev) J[pr->a] = pr->b;
+  J[TT.file[0].len+1] = TT.file[1].len+1; //mark boundary
 
-  for (i = k + 1; i >= 0; i--) free_candidates(kcand[i]);
+  for (i = k+1; i>=0; i--) llist_traverse(kcand[i], free);
   free(kcand);
 
-  for (i = 1; i <= file[0].len; i++) { // jackpot?
+  for (i = 1; i<=TT.file[0].len; i++) { // jackpot?
     if (!J[i]) continue;
 
-    fseek(file[0].fp, TT.offset[0][i - 1], SEEK_SET);
-    fseek(file[1].fp, TT.offset[1][J[i] - 1], SEEK_SET);
+    if (fseek(TT.file[0].fp, TT.offset[0][i-1], SEEK_SET)
+     || fseek(TT.file[1].fp, TT.offset[1][J[i]-1], SEEK_SET))
+       perror_exit("fseek");
 
-    for (j = J[i]; i <= file[0].len && J[i] == j; i++, j++) {
+    for (j = J[i]; i<=TT.file[0].len && J[i]==j; i++, j++) {
       int tok0 = 0, tok1 = 0;
 
       do {
-        tok0 = read_tok(file[0].fp, NULL, tok0);
-        tok1 = read_tok(file[1].fp, NULL, tok1);
+        tok0 = read_tok(TT.file[0].fp, NULL, tok0);
+        tok1 = read_tok(TT.file[1].fp, NULL, tok1);
         if (((tok0 ^ tok1) & empty) || ((tok0 & 0xff) != (tok1 & 0xff)))
           J[i] = 0;
       } while (!(tok0 & tok1 & empty));
@@ -378,78 +333,132 @@
   char *bufi, *bufj;
 
   TT.is_binary = 0; //loop calls to diff
-  TT.status = SAME;
+  TT.differ = 0;
 
   for (i = 0; i < 2; i++) {
-    if (IS_STDIN(files[i])) file[i].fp = read_stdin();
-    else file[i].fp = fopen(files[i], "r");
+    if ((j = !strcmp(files[i], "-")) || S_ISFIFO(TT.st[i].st_mode)) {
+      char *tmp_name;
+      int srcfd = j ? 0 : open(files[i], O_RDONLY),
+        tmpfd = xtempfile("fifo", &tmp_name);
 
-    if (!file[i].fp){
-      perror_msg("%s",files[i]);
-      TT.status = 2;
-      return NULL; //return SAME
+      unlink(tmp_name);
+      free(tmp_name);
+
+      xsendfile(srcfd, tmpfd);
+      if (!j) close(srcfd);
+      TT.file[i].fp = fdopen(tmpfd, "r");
+    } else TT.file[i].fp = fopen(files[i], "r");
+
+    if (!TT.file[i].fp) {
+      perror_msg("%s", files[i]);
+      TT.differ = 2;
+      return 0; //return SAME
     }
   }
 
   s = sizeof(toybuf)/2;
   bufi = toybuf;
-  bufj = (toybuf + s);
+  bufj = toybuf+s;
 
-  fseek(file[0].fp, 0, SEEK_SET);
-  fseek(file[1].fp, 0, SEEK_SET);
+  if (fseek(TT.file[0].fp, 0, SEEK_SET) || fseek(TT.file[1].fp, 0, SEEK_SET))
+    perror_exit("fseek");
 
-  if (toys.optflags & FLAG_a) return create_j_vector();
+  if (FLAG(a)) return create_j_vector();
 
   while (1) {
-    i = fread(bufi, 1, s, file[0].fp);
-    j = fread(bufj, 1, s, file[1].fp);
+    i = fread(bufi, 1, s, TT.file[0].fp);
+    j = fread(bufj, 1, s, TT.file[1].fp);
 
-    if (i != j) TT.status = DIFFER;
+    if (i != j) TT.differ = 1;
 
-    for (t = 0; t < i && !TT.is_binary; t++)
-      if (!bufi[t]) TT.is_binary = 1;
-    for (t = 0; t < j && !TT.is_binary; t++)
-      if (!bufj[t]) TT.is_binary = 1;
+    for (t = 0; t < i && !TT.is_binary; t++) if (!bufi[t]) TT.is_binary = 1;
+    for (t = 0; t < j && !TT.is_binary; t++) if (!bufj[t]) TT.is_binary = 1;
 
-    i = MIN(i, j);
-    for (t = 0; t < i; t++)
-      if (bufi[t] != bufj[t]) TT.status = DIFFER;
+    i = minof(i, j);
+    for (t = 0; t < i; t++) if (bufi[t] != bufj[t]) TT.differ = 1;
 
     if (!i || !j) break;
   }
-  if (TT.is_binary || (TT.status == SAME)) return NULL;
+  if (TT.is_binary || !TT.differ) return 0;
+
   return create_j_vector();
 }
 
+static void print_line_matching_regex(int a, regex_t *reg, int *off_set, FILE *fp) {
+  int i = 0, j = 0, line_buf_size = 100, cc = 0;
+  char* line = xzalloc(line_buf_size * sizeof(char));
+  for (i = a; a > 0; --i) {
+    int line_len = 0;
+    if (fseek(fp, off_set[i - 1], SEEK_SET)) perror_exit("fseek failed");
+    for (j = 0; j < (off_set[i] - off_set[i - 1]); j++) {
+      cc = fgetc(fp);
+      if (cc == EOF || cc == '\n') {
+        break;
+      }
+      ++line_len;
+      if (line_len >= line_buf_size) {
+        line_buf_size = line_buf_size * 11 / 10;
+        line = xrealloc(line, line_buf_size*sizeof(char));
+      }
+      line[j] = cc;
+    }
+    line[line_len] = '\0';
+    if (!regexec0(reg, line, line_len, 0, NULL, 0)) {
+      printf(" %s", line);
+      break;
+    }
+  }
+  free(line);
+}
+
 static void print_diff(int a, int b, char c, int *off_set, FILE *fp)
 {
   int i, j, cc, cl;
-  char *reset = NULL;
+  char *reset = 0, *fmt = 0;
 
-  if (c != ' ' && (toys.optflags & FLAG_color)) {
-    printf("\e[%dm", c == '+' ? 32 : 31);
+  if (!TT.new_line_format && c!=' ' && FLAG(color)) {
+    printf("\e[%dm", 31+(c=='+'));
     reset = "\e[0m";
   }
 
   for (i = a; i <= b; i++) {
-    fseek(fp, off_set[i - 1], SEEK_SET);
+    if (fseek(fp, off_set[i - 1], SEEK_SET)) perror_exit("fseek failed");
+    if (TT.new_line_format) {
+      if (c == '+') fmt = TT.new_line_format;
+      else if (c == '-') fmt = TT.old_line_format;
+      else fmt = TT.unchanged_line_format;
+      while (*fmt) {
+        if (*fmt == '%') {
+          fmt++;
+          char f = *fmt++;
+          if (f == '%') putchar('%');
+          else if (f == 'l' || f == 'L') {
+            for (j = 0; j <  (off_set[i] - off_set[i - 1]); j++) {
+              cc = fgetc(fp);
+              if (cc == EOF) break;
+              if (cc != '\n' || f == 'L') putchar(cc);
+            }
+          } else error_exit("Unrecognized format specifier %%%c", f);
+        } else putchar(*fmt++);
+      }
+      continue;
+    }
     putchar(c);
-    if (toys.optflags & FLAG_T) putchar('\t');
+    if (FLAG(T)) putchar('\t');
     for (j = 0, cl = 0; j <  (off_set[i] - off_set[i - 1]); j++) {
       cc = fgetc(fp);
       if (cc == EOF) {
-        printf("%s\n\\ No newline at end of file\n", reset ? reset : "");
+        printf("%s\n\\ No newline at end of file\n", reset ? : "");
         return;
       }
-      if ((cc == '\t') && (toys.optflags & FLAG_t))
-        do putchar(' '); while (++cl & 7);
+      if ((cc == '\t') && FLAG(t)) do putchar(' '); while (++cl & 7);
       else {
         putchar(cc); //xputc has calls to fflush, it hurts performance badly.
         cl++;
       }
     }
   }
-  if (reset) printf("%s", reset);
+  if (reset) xputsn(reset);
 }
 
 static char *concat_file_path(char *path, char *default_path)
@@ -488,14 +497,14 @@
 {
   char *full_path;
 
-  dir[TT.dir_num].list = xrealloc(dir[TT.dir_num].list,
+  TT.dir[TT.dir_num].list = xrealloc(TT.dir[TT.dir_num].list,
       (TT.size + 1)*sizeof(char*));
   TT.size++;
   full_path = dirtree_path(node, NULL);
-  dir[TT.dir_num].list[TT.size - 1] = full_path;
+  TT.dir[TT.dir_num].list[TT.size - 1] = full_path;
 }
 
-static int list_dir (struct dirtree *node)
+static int list_dir(struct dirtree *node)
 {
   int ret = 0;
 
@@ -506,9 +515,9 @@
     return (DIRTREE_RECURSE|DIRTREE_SYMFOLLOW);
   }
 
-  if (S_ISDIR(node->st.st_mode) && (toys.optflags & FLAG_r)) {
-    if (!(toys.optflags & FLAG_N)) ret = skip(node);
-    if (!ret) return (DIRTREE_RECURSE|DIRTREE_SYMFOLLOW);
+  if (S_ISDIR(node->st.st_mode) && FLAG(r)) {
+    if (!FLAG(N)) ret = skip(node);
+    if (!ret) return DIRTREE_RECURSE|DIRTREE_SYMFOLLOW;
     else {
       add_to_list(node); //only at one side.
       return 0;
@@ -519,58 +528,43 @@
   }
 }
 
-static int cmp(const void *p1, const void *p2)
+static int cmp(void *p1, void *p2)
 {
-   return strcmp(* (char * const *)p1, * (char * const *)p2);
+   return strcmp(*(char **)p1, *(char **)p2);
 }
 
 // quote and escape filenames that have awkward characters
 char *quote_filename(char *filename)
 {
-  char *to = "abfnrtv\"\\", *from = "\a\b\f\n\r\t\v\"\\";
-  char *result, *s, *t;
-  size_t len = 0;
-  int quote = 0;
+  char *to = "abfnrtv\"\\", *from = "\a\b\f\n\r\t\v\"\\", *s, *t=0, *u;
+  int len, quote = 0;
 
-  // calculate memory usage and presence of quotes
-  for (s = filename; *s; s++) {
-    if (*s == '\a' || *s == '\b' || *s == '\f' || *s == '\r' || *s == '\v'
-      || *s == '\n' || *s == '\t' || *s == '"' || *s == '\\')
-    {
-      quote = 1;
-      len += 2;
-    } else if (*s == ' ') {
-      quote = 1;
-      len++;
-    } else if (*s < 0x20 || *s >= 0x80) {
-      quote = 1;
-      len += 4;
-    } else {
-      len++;
+  for (;;) {
+    // measure escapes on first pass, write on second
+    len = 0;
+    for (s = filename; *s; s++) {
+      if ((u = strchr(from, *s))) {
+        if (t) t[len] = '\\', t[len+1] = to[u-from];
+        len += 2;
+      } else if (*s<0x20 || *s>=0x80)
+        len += snprintf(t+len, 5*!!t, "\\%.3o", *s);
+      else {
+        if (t) t[len] = *s;
+        len++;
+      }
     }
-  }
+    if (t) {
+      if (quote) t[len++] = '"';
+      t[len] = 0;
 
-  // construct the new string
-  result = xmalloc(len + (quote ? 2 : 0) + 1);
-  t = result;
-  if (quote) *t++ = '"';
-  for (s = filename; *s; s++) {
-    if (*s == '\a' || *s == '\b' || *s == '\f' || *s == '\r' || *s == '\v'
-      || *s == '\n' || *s == '\t' || *s == '"' || *s == '\\')
-    {
-      *t = '\\';
-      t[1] = to[strchr(from, *s) - from];
-      t += 2;
-    } else if (*s < 0x20 || *s >= 0x80) {
-      sprintf(t, "\\%.3o", *s);
-      t += 4;
-    } else {
-      *t++ = *s;
+      return t-quote;
     }
+
+    // construct the new string
+    quote = strlen(filename)!=len || strchr(filename, ' ');
+    t = xmalloc(len+1+2*quote);
+    if (quote) *t++ = '"';
   }
-  if (quote) *t++ = '"';
-  *t = 0;
-  return result;
 }
 
 static void show_label(char *prefix, char *filename, struct stat *sb)
@@ -586,34 +580,38 @@
 
 static void do_diff(char **files)
 {
-
   long i = 1, size = 1, x = 0, change = 0, ignore_white,
    start1, end1, start2, end2;
   struct diff *d;
-  struct arg_list *llist = TT.L_list;
+  struct arg_list *llist = TT.L;
   int *J;
+  regex_t reg;
   
   TT.offset[0] = TT.offset[1] = NULL;
   J = diff(files);
 
   if (!J) return; //No need to compare, have to status only
 
+  if (TT.F) {
+    xregcomp(&reg, TT.F, 0);
+  }
+
   d = xzalloc(size *sizeof(struct diff));
   do {
     ignore_white = 0;
-    for (d[x].a = i; d[x].a <= file[0].len; d[x].a++) {
+    for (d[x].a = i; d[x].a<=TT.file[0].len; d[x].a++) {
       if (J[d[x].a] != (J[d[x].a - 1] + 1)) break;
       else continue;
     }
     d[x].c = (J[d[x].a - 1] + 1);
 
-    for (d[x].b = (d[x].a - 1); d[x].b <= file[0].len; d[x].b++) {
+    for (d[x].b = (d[x].a - 1); d[x].b<=TT.file[0].len; d[x].b++) {
       if (J[d[x].b + 1]) break;
       else continue;
     }
     d[x].d = (J[d[x].b + 1] - 1);
 
-    if ((toys.optflags & FLAG_B)) {
+    if (FLAG(B)) {
       if (d[x].a <= d[x].b) {
         if ((TT.offset[0][d[x].b] - TT.offset[0][d[x].a - 1])
             == (d[x].b - d[x].a + 1))
@@ -625,83 +623,85 @@
       }
     }
 
-    if ((d[x].a <= d[x].b || d[x].c <= d[x].d) && !ignore_white)
-      change = 1; //is we have diff ?
+    //is we have diff ?   TODO: lolcat?
+    if ((d[x].a <= d[x].b || d[x].c <= d[x].d) && !ignore_white) change = 1;
 
     if (!ignore_white) d = xrealloc(d, (x + 2) *sizeof(struct diff));
     i = d[x].b + 1;
-    if (i > file[0].len) break;
+    if (i>TT.file[0].len) break;
     J[d[x].b] = d[x].d;
     if (!ignore_white) x++;
-  } while (i <= file[0].len);
+  } while (i<=TT.file[0].len);
 
   i = x+1;
-  TT.status = change; //update status, may change bcoz of -w etc.
+  TT.differ = change; //update status, may change bcoz of -w etc.
 
-  if (!(toys.optflags & FLAG_q) && change) {  //start of !FLAG_q
-    if (toys.optflags & FLAG_color) printf("\e[1m");
-    if (toys.optflags & FLAG_L) printf("--- %s\n", llist->arg);
-    else show_label("---", files[0], &(TT).st[0]);
-    if (((toys.optflags & FLAG_L) && !llist->next) || !(toys.optflags & FLAG_L))
-      show_label("+++", files[1], &(TT).st[1]);
-    else {
-      while (llist->next) llist = llist->next;
-      printf("+++ %s\n", llist->arg);
+  if (!FLAG(q) && change) {
+    if (!TT.new_line_format) {
+      if (FLAG(color)) printf("\e[1m");
+      if (FLAG(L)) printf("--- %s\n", llist->arg);
+      else show_label("---", files[0], &(TT).st[0]);
+      if (!FLAG(L) || !llist->next) show_label("+++", files[1], &(TT).st[1]);
+      else {
+        while (llist->next) llist = llist->next;
+        printf("+++ %s\n", llist->arg);
+      }
+      if (FLAG(color)) printf("\e[0m");
     }
-    if (toys.optflags & FLAG_color) printf("\e[0m");
 
     struct diff *t, *ptr1 = d, *ptr2 = d;
     while (i) {
       long a,b;
 
-      if (TT.ct > file[0].len) TT.ct = file[0].len; //trim context to file len.
+      // trim context to file len.
+      if (TT.new_line_format || TT.U>TT.file[0].len) TT.U = TT.file[0].len;
       if (ptr1->b < ptr1->a && ptr1->d < ptr1->c) {
         i--;
         continue;
       }
       //Handle the context stuff
       a =  ptr1->a;
-      b =  ptr1->b;
-
-      b  = MIN(file[0].len, b);
-      if (i == x + 1) ptr1->suff = MAX(1,a - TT.ct);
-      else {
-        if ((ptr1 - 1)->prev >= (ptr1->a - TT.ct))
-          ptr1->suff = (ptr1 - 1)->prev + 1;
-        else ptr1->suff =  ptr1->a - TT.ct;
-      }
+      b = minof(TT.file[0].len, ptr1->b);
+      if (i == x + 1) ptr1->suff = maxof(1, a-TT.U);
+      else if (ptr1[-1].prev >= ptr1->a-TT.U) ptr1->suff = ptr1[-1].prev+1;
+      else ptr1->suff =  ptr1->a-TT.U;
 calc_ct:
       if (i > 1) {
-        if ((ptr2->b + TT.ct) >= (ptr2  + 1)->a) {
+        if ((ptr2->b + TT.U) >= (ptr2  + 1)->a) {
           ptr2++;
           i--;
           goto calc_ct;
-        } else ptr2->prev = ptr2->b + TT.ct;
+        } else ptr2->prev = ptr2->b + TT.U;
       } else ptr2->prev = ptr2->b;
       start1 = (ptr2->prev - ptr1->suff + 1);
       end1 = (start1 == 1) ? -1 : start1;
-      start2 = MAX(1, ptr1->c - (ptr1->a - ptr1->suff));
+      start2 = maxof(1, ptr1->c - (ptr1->a - ptr1->suff));
       end2 = ptr2->prev - ptr2->b + ptr2->d;
 
-      if (toys.optflags & FLAG_color) printf("\e[36m");
-      printf("@@ -%ld", start1 ? ptr1->suff: (ptr1->suff -1));
-      if (end1 != -1) printf(",%ld ", ptr2->prev-ptr1->suff + 1);
-      else putchar(' ');
+      if (!TT.new_line_format) {
+        if (FLAG(color)) printf("\e[36m");
+        printf("@@ -%ld", start1 ? ptr1->suff: (ptr1->suff -1));
+        if (end1 != -1) printf(",%ld ", ptr2->prev-ptr1->suff + 1);
+        else putchar(' ');
 
-      printf("+%ld", (end2 - start2 + 1) ? start2: (start2 -1));
-      if ((end2 - start2 +1) != 1) printf(",%ld ", (end2 - start2 +1));
-      else putchar(' ');
-      printf("@@");
-      if (toys.optflags & FLAG_color) printf("\e[0m");
-      putchar('\n');
+        printf("+%ld", (end2 - start2 + 1) ? start2: (start2 -1));
+        if ((end2 - start2 +1) != 1) printf(",%ld ", (end2 - start2 +1));
+        else putchar(' ');
+        printf("@@");
+        if (FLAG(color)) printf("\e[0m");
+        if (TT.F) {
+          print_line_matching_regex(ptr1->suff-1, &reg, TT.offset[0], TT.file[0].fp);
+        }
+        putchar('\n');
+      }
 
       for (t = ptr1; t <= ptr2; t++) {
-        if (t== ptr1) print_diff(t->suff, t->a-1, ' ', TT.offset[0], file[0].fp);
-        print_diff(t->a, t->b, '-', TT.offset[0], file[0].fp);
-        print_diff(t->c, t->d, '+', TT.offset[1], file[1].fp);
+        if (t==ptr1) print_diff(t->suff, t->a-1, ' ', TT.offset[0], TT.file[0].fp);
+        print_diff(t->a, t->b, '-', TT.offset[0], TT.file[0].fp);
+        print_diff(t->c, t->d, '+', TT.offset[1], TT.file[1].fp);
         if (t == ptr2)
-          print_diff(t->b+1, (t)->prev, ' ', TT.offset[0], file[0].fp);
-        else print_diff(t->b+1, (t+1)->a-1, ' ', TT.offset[0], file[0].fp);
+          print_diff(t->b+1, (t)->prev, ' ', TT.offset[0], TT.file[0].fp);
+        else print_diff(t->b+1, (t+1)->a-1, ' ', TT.offset[0], TT.file[0].fp);
       }
       ptr2++;
       ptr1 = ptr2;
@@ -716,16 +716,10 @@
 
 static void show_status(char **files)
 {
-  switch (TT.status) {
-    case SAME:
-      if (toys.optflags & FLAG_s)
-        printf("Files %s and %s are identical\n",files[0], files[1]);
-      break;
-    case DIFFER:
-      if ((toys.optflags & FLAG_q) || TT.is_binary)
-        printf("Files %s and %s differ\n",files[0], files[1]);
-      break;
-  }
+  if (TT.differ==2) return; // TODO: needed?
+  if (TT.differ ? FLAG(q) || TT.is_binary : FLAG(s))
+    printf("Files %s and %s %s\n", files[0], files[1],
+      TT.differ ? "differ" : "are identical");
 }
 
 static void create_empty_entry(int l , int r, int j)
@@ -734,54 +728,41 @@
   char *f[2], *path[2];
   int i;
 
-  if (j > 0 && (toys.optflags & FLAG_N)) {
-    path[0] = concat_file_path(dir[0].list[0], dir[1].list[r] + TT.len[1]);
-    f[0] = "/dev/null";
-    path[1] = f[1] = dir[1].list[r];
-    stat(f[1], &st[0]);
-    st[1] = st[0];
-  }
-  else if (j < 0 && (toys.optflags & FLAG_N)) {
-    path[1] = concat_file_path(dir[1].list[0], dir[0].list[l] + TT.len[0]);
-    f[1] = "/dev/null";
-    path[0] = f[0] = dir[0].list[l];
-    stat(f[0], &st[0]);
-    st[1] = st[0];
+  for (i = 0; i < 2; i++) {
+    if (j) {
+      if (!FLAG(N) || i!=(j>0)) continue;
+      path[!i] = concat_file_path(TT.dir[!i].list[0],
+        TT.dir[i].list[i ? r : l]+TT.len[i]);
+      f[!i] = "/dev/null";
+    }
+    path[i] = f[i] = TT.dir[i].list[i ? r : l];
+    stat(f[i], st+i);
+    if (j) st[!i] = st[i];
   }
 
-  if (!j) {
-    for (i = 0; i < 2; i++) {
-      path[i] = f[i] = dir[i].list[!i ? l: r];
-      stat(f[i], &st[i]);
+  for (i = 0; i<2; i++) {
+    if (!S_ISREG(st[i].st_mode) && !S_ISDIR(st[i].st_mode)) {
+      printf("File %s is not a regular file or directory and was skipped\n",
+        path[i]);
+      break;
     }
   }
 
-  if (S_ISDIR(st[0].st_mode) && S_ISDIR(st[1].st_mode))
+  if (i != 2);
+  else if (S_ISDIR(st[0].st_mode) && S_ISDIR(st[1].st_mode))
     printf("Common subdirectories: %s and %s\n", path[0], path[1]);
-  else if (!S_ISREG(st[0].st_mode) && !S_ISDIR(st[0].st_mode))
-    printf("File %s is not a regular file or directory "
-        "and was skipped\n", path[0]);
-  else if (!S_ISREG(st[1].st_mode) && !S_ISDIR(st[1].st_mode))
-    printf("File %s is not a regular file or directory "
-        "and was skipped\n", path[1]);
-  else if (S_ISDIR(st[0].st_mode) != S_ISDIR(st[1].st_mode)) {
-    if (S_ISDIR(st[0].st_mode))
-      printf("File %s is a %s while file %s is a"
-          " %s\n", path[0], "directory", path[1], "regular file");
-    else
-      printf("File %s is a %s while file %s is a"
-          " %s\n", path[0], "regular file", path[1], "directory");
+  else if ((i = S_ISDIR(st[0].st_mode)) != S_ISDIR(st[1].st_mode)) {
+    char *fidir[] = {"directory", "regular file"};
+    printf("File %s is a %s while file %s is a %s\n",
+      path[0], fidir[!i], path[1], fidir[i]);
   } else {
     do_diff(f);
     show_status(path);
-    if (file[0].fp) fclose(file[0].fp);
-    if (file[1].fp) fclose(file[1].fp);
+    if (TT.file[0].fp) fclose(TT.file[0].fp);
+    if (TT.file[1].fp) fclose(TT.file[1].fp);
   }
 
-  if ((toys.optflags & FLAG_N) && j) {
-    if (j > 0) free(path[0]);
-    else free(path[1]);
-  }
+  if (FLAG(N) && j) free(path[j<=0]);
 }
 
 static void diff_dir(int *start)
@@ -790,102 +771,89 @@
 
   l = start[0]; //left side file start
   r = start[1]; //right side file start
-  while (l < dir[0].nr_elm && r < dir[1].nr_elm) {
-    if ((j = strcmp ((dir[0].list[l] + TT.len[0]),
-            (dir[1].list[r] + TT.len[1]))) && !(toys.optflags & FLAG_N)) {
+  while (l < TT.dir[0].nr_elm && r < TT.dir[1].nr_elm) {
+    if ((j = strcmp (TT.dir[0].list[l]+TT.len[0],
+            (TT.dir[1].list[r]+TT.len[1]))) && !FLAG(N)) {
       if (j > 0) {
-        printf ("Only in %s: %s\n", dir[1].list[0], dir[1].list[r] + TT.len[1]);
-        free(dir[1].list[r]);
-        r++;
+        printf("Only in %s: %s\n", TT.dir[1].list[0], TT.dir[1].list[r]+TT.len[1]);
+        free(TT.dir[1].list[r++]);
       } else {
-        printf ("Only in %s: %s\n", dir[0].list[0], dir[0].list[l] + TT.len[0]);
-        free(dir[0].list[l]);
-        l++;
+        printf ("Only in %s: %s\n", TT.dir[0].list[0], TT.dir[0].list[l]+TT.len[0]);
+        free(TT.dir[0].list[l++]);
       }
-      TT.status = DIFFER;
+      TT.differ = 1;
     } else {
       create_empty_entry(l, r, j); //create non empty dirs/files if -N.
-      if (j > 0) {
-        free(dir[1].list[r]);
-        r++;
-      } else if (j < 0) {
-        free(dir[0].list[l]);
-        l++;
-      } else {
-        free(dir[1].list[r]);
-        free(dir[0].list[l]);
-        l++;
-        r++;
-      }
+      if (j>=0) free(TT.dir[1].list[r++]);
+      if (j<=0) free(TT.dir[0].list[l++]);
     }
   }
 
-  if (l == dir[0].nr_elm) {
-    while (r < dir[1].nr_elm) {
-      if (!(toys.optflags & FLAG_N)) {
-        printf ("Only in %s: %s\n", dir[1].list[0], dir[1].list[r] + TT.len[1]);
-        TT.status = DIFFER;
+  if (l == TT.dir[0].nr_elm) {
+    while (r<TT.dir[1].nr_elm) {
+      if (!FLAG(N)) {
+        printf ("Only in %s: %s\n", TT.dir[1].list[0], TT.dir[1].list[r]+TT.len[1]);
+        TT.differ = 1;
       } else create_empty_entry(l, r, 1);
-      free(dir[1].list[r]);
-      r++;
+      free(TT.dir[1].list[r++]);
     }
-  } else if (r == dir[1].nr_elm) {
-    while (l < dir[0].nr_elm) {
-      if (!(toys.optflags & FLAG_N)) {
-        printf ("Only in %s: %s\n", dir[0].list[0], dir[0].list[l] + TT.len[0]);
-        TT.status = DIFFER;
+  } else if (r == TT.dir[1].nr_elm) {
+    while (l<TT.dir[0].nr_elm) {
+      if (!FLAG(N)) {
+        printf ("Only in %s: %s\n", TT.dir[0].list[0], TT.dir[0].list[l]+TT.len[0]);
+        TT.differ = 1;
       } else create_empty_entry(l, r, -1);
-      free(dir[0].list[l]);
-      l++;
+      free(TT.dir[0].list[l++]);
     }
   }
-  free(dir[0].list[0]); //we are done, free root nodes too
-  free(dir[1].list[0]);
+  free(TT.dir[0].list[0]); //we are done, free root nodes too
+  free(TT.dir[0].list);
+  free(TT.dir[1].list[0]);
+  free(TT.dir[1].list);
 }
 
 void diff_main(void)
 {
   int j = 0, k = 1, start[2] = {1, 1};
-  char *files[2];
+  char **files = toys.optargs;
 
   toys.exitval = 2;
-
-  if ((toys.optflags & FLAG_color) && !isatty(1)) toys.optflags ^= FLAG_color;
+  if (FLAG(color) && !isatty(1)) toys.optflags ^= FLAG_color;
 
   for (j = 0; j < 2; j++) {
-    files[j] = toys.optargs[j];
-    if (IS_STDIN(files[j])) {
-      if (fstat(0, &TT.st[j]) == -1)
-        perror_exit("can't fstat %s", files[j]);
-    } else {
-      xstat(files[j], &TT.st[j]);
-    }
+    if (IS_STDIN(files[j])) fstat(0, &TT.st[j]);
+    else xstat(files[j], &TT.st[j]);
   }
 
-  if ((IS_STDIN(files[0]) || IS_STDIN(files[1]))
-      && (S_ISDIR(TT.st[0].st_mode) || S_ISDIR(TT.st[1].st_mode)))
-    error_exit("can't compare stdin to directory");
+  if (S_ISDIR(TT.st[0].st_mode) != S_ISDIR(TT.st[1].st_mode))
+    error_exit("can't compare directory to non-directory");
 
-  if ((TT.st[0].st_ino == TT.st[1].st_ino) //physicaly same device
-      && (TT.st[0].st_dev == TT.st[1].st_dev)) {
+  if (TT.unchanged_line_format || TT.old_line_format || TT.new_line_format) {
+    if (S_ISDIR(TT.st[0].st_mode) && S_ISDIR(TT.st[1].st_mode))
+      error_exit("can't use line format with directories");
+    if (!TT.unchanged_line_format) TT.unchanged_line_format = "%l\n";
+    if (!TT.old_line_format) TT.old_line_format = "%l\n";
+    if (!TT.new_line_format) TT.new_line_format = "%l\n";
+  }
+
+  if (same_file(TT.st, TT.st+1)) {
     toys.exitval = 0;
     return show_status(files);
   }
 
   if (S_ISDIR(TT.st[0].st_mode) && S_ISDIR(TT.st[1].st_mode)) {
     for (j = 0; j < 2; j++) {
-      memset(&dir[j], 0, sizeof(struct dir_t));
+      memset(TT.dir+j, 0, sizeof(*TT.dir));
       dirtree_flagread(files[j], DIRTREE_SYMFOLLOW, list_dir);
-      dir[j].nr_elm = TT.size; //size updated in list_dir
-      qsort(&(dir[j].list[1]), (TT.size - 1), sizeof(char*), cmp);
+      TT.dir[j].nr_elm = TT.size; //size updated in list_dir
+      qsort(&TT.dir[j].list[1], TT.size-1, sizeof(char *), (void *)cmp);
 
-      TT.len[j] = strlen(dir[j].list[0]); //calc root node len
-      TT.len[j] += (dir[j].list[0][TT.len[j] -1] != '/');
+      TT.len[j] = strlen(TT.dir[j].list[0]); //calc root node len
+      TT.len[j] += TT.dir[j].list[0][TT.len[j]-1] != '/';
 
-      if (toys.optflags & FLAG_S) {
-        while (k < TT.size && strcmp(dir[j].list[k] +
-              TT.len[j], TT.start) < 0) {
-          start[j] += 1;
+      if (FLAG(S)) {
+        while (k<TT.size && strcmp(TT.dir[j].list[k]+TT.len[j], TT.S)<0) {
+          start[j]++;
           k++;
         }
       }
@@ -894,21 +862,18 @@
       k = 1;
     }
     diff_dir(start);
-    free(dir[0].list); //free array
-    free(dir[1].list);
   } else {
     if (S_ISDIR(TT.st[0].st_mode) || S_ISDIR(TT.st[1].st_mode)) {
       int d = S_ISDIR(TT.st[0].st_mode);
       char *slash = strrchr(files[d], '/');
 
-      files[1 - d] = concat_file_path(files[1 - d], slash ? slash + 1 : files[d]);
-      if ((stat(files[1 - d], &TT.st[1 - d])) == -1)
-        perror_exit("%s", files[1 - d]);
+      files[!d] = concat_file_path(files[!d], slash ? slash+1 : files[d]);
+      if (stat(files[!d], &TT.st[!d])) perror_exit("%s", files[!d]);
     }
     do_diff(files);
     show_status(files);
-    if (file[0].fp) fclose(file[0].fp);
-    if (file[1].fp) fclose(file[1].fp);
+    if (TT.file[0].fp) fclose(TT.file[0].fp);
+    if (TT.file[1].fp) fclose(TT.file[1].fp);
   }
-  toys.exitval = TT.status; //exit status will be the status
+  toys.exitval = TT.differ; //exit status will be the status
 }
diff --git a/toys/pending/getopt.c b/toys/pending/getopt.c
index dcef314..225db57 100644
--- a/toys/pending/getopt.c
+++ b/toys/pending/getopt.c
@@ -22,6 +22,7 @@
 
 #define FOR_getopt
 #include "toys.h"
+#include <getopt.h> // Everything else uses lib/args.c
 
 GLOBALS(
   struct arg_list *l;
diff --git a/toys/pending/git.c b/toys/pending/git.c
new file mode 100644
index 0000000..8242148
--- /dev/null
+++ b/toys/pending/git.c
@@ -0,0 +1,657 @@
+/* git.c - A minimal git clone
+ *
+ * Copyright 2022 Moritz C. Weber <mo.c.weber@gmail.com>
+ *
+ * See https://git-scm.com/docs/git-init
+ * https://git-scm.com/docs/git-remote
+ * https://git-scm.com/docs/git-fetch
+ * https://git-scm.com/docs/git-checkout
+ * https://git-scm.com/docs/pack-format
+ * https://git-scm.com/docs/index-format
+ * https://www.alibabacloud.com/blog/a-detailed-explanation-of-the-underlying-data-structures-and-principles-of-git_597391
+ * https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt
+ * https://stackoverflow.com/a/14303988
+ * https://stackoverflow.com/a/21599232
+ * https://github.com/tarruda/node-git-core/blob/master/src/js/delta.js
+
+
+USE_GITCLONE(NEWTOY(gitclone, "<1", TOYFLAG_USR|TOYFLAG_BIN))
+USE_GITINIT(NEWTOY(gitinit, "<1", TOYFLAG_USR|TOYFLAG_BIN))
+USE_GITREMOTE(NEWTOY(gitremote, "<1", TOYFLAG_USR|TOYFLAG_BIN))
+USE_GITFETCH(NEWTOY(gitfetch, 0, TOYFLAG_USR|TOYFLAG_BIN))
+USE_GITCHECKOUT(NEWTOY(gitcheckout, "<1", TOYFLAG_USR|TOYFLAG_BIN))
+
+config GITCOMPAT
+  bool "gitcompat"
+  default n
+  help
+    Enable git compatible repos instead of minimal clone downloader.
+
+config GITCLONE
+  bool "gitclone"
+  default n
+  help
+    usage: gitclone URL
+    A minimal git clone.
+
+config GITINIT
+  bool "gitinit"
+  default n
+  help
+    usage: gitinit NAME
+    A minimal git init.
+
+config GITREMOTE
+  bool "gitremote"
+  default n
+  help
+    usage: gitremote URL
+    A minimal git remote add origin.
+
+config GITFETCH
+  bool "gitfetch"
+  default n
+  help
+    usage: gitfetch
+    A minimal git fetch.
+
+config GITCHECKOUT
+  bool "gitcheckout"
+  default n
+  help
+    usage: gitcheckout <branch>
+    A minimal git checkout.
+*/
+
+#define TT  this.git
+#define FOR_gitclone
+#include "toys.h"
+#include "openssl/sha.h" //ToDo: borrowed from OpenSSL to not pipe or refactor the SHA1SUM in toybox
+#include "zlib.h"  //ToDo: borrowed from libz to not refactor deflate.c
+
+GLOBALS(
+  char *url, *name; //git repo remote url and init directory name
+  struct IndexV2 *i; //git creates a index for each pack file, git clone just needs one index for the received pack file
+)
+
+//git index format v2 described at https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L266
+struct IndexV2 {
+  char header[8];// Git 4 byte magic number and 4 byte version number
+  unsigned fot[256];//A fan-out table
+  char (*sha1)[20];//Table of sorted object names(SHA1 hashes)
+  unsigned *crc, *offset;//Table of 4-bit CRC32 values and object offsets in pack file
+  long long *offset64; //8 byte offests -- not supported yet
+  char packsha1[20], idxsha1[20];//SHA1 hash of pack file and SHA1 hash of index file
+};
+
+//TODO:This function is not used before git clone persists an index V2
+static void read_index(struct IndexV2 *i)
+{
+  FILE *fpi;
+
+  i = xmalloc(sizeof(i));
+  i->sha1 = malloc(20);
+  i->crc = malloc(sizeof(unsigned));
+  i->offset = malloc(sizeof(unsigned));
+  i->offset64 = malloc(sizeof(long long));
+  //TODO: not used yet as index is not persisted yet
+  if (access(".git/object/pack/temp.idx", F_OK)==0) {
+    //persistance needed for other git commands (not clone)
+    fpi = fopen(".git/object/pack/temp.idx", "rb");
+    printf("read header\n");
+    fread(i->header, sizeof(i->header), 1, fpi);
+    printf("Header: %s..Read fot\n", i->header);
+    fread(i->fot, 4, 256, fpi);
+    printf("Elements %d..Read sha1\n", i->fot[255]);
+    fread(i->sha1, sizeof(i->fot), i->fot[255], fpi);
+    printf("read crc\n");
+    fread(i->crc, sizeof(i->fot), i->fot[255], fpi);
+    printf("read offset\n");
+    fread(i->offset, sizeof(i->fot), i->fot[255], fpi);
+    //TODO: Offsets for file size 2G missing here
+    printf("read packsha\n");
+    fread(i->packsha1, 20, 1, fpi);
+    printf("read idxsha\n");
+    fread(i->idxsha1, 20, 1, fpi);
+    fclose(fpi);
+  }
+}
+
+long bsearchpos(const char *k, const char *a, size_t h, size_t w)
+{
+  long l = 0, m = 0, r = 0;
+
+  if (!h) return 0;
+  while (h>0) {
+    m = l+(h/2);
+    r = strncmp(k, a+(m*w), 20);
+    if (!r||h==1) break; //match on search or position for insert
+    if (r<0) { h /= 2; } else { l = m; h -= h/2; }
+  }
+
+  //For inserts check if insert is bigger  obj at identified position
+  return m += (r>0) ? 1 : 0;
+}
+
+//find offset position in packfile for given SHA1 hash
+long get_index(struct IndexV2 *i, char *h)
+{
+  long pos = bsearchpos(h, i->sha1[0], i->fot[255], 20);
+ return i->offset[pos];
+}
+
+//https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L35
+//https://yqintl.alicdn.com/eef7fe4f22cc97912cee011c99d3fe5821ae9e88.png
+//read type and length of an packed object at a given offset
+unsigned long long unpack(FILE *fpp, int *type, long *offset)
+{
+  int bitshift= 4;
+  unsigned long long length = 0;
+  char data;
+
+  printf("Start unpack\n");
+  fseek(fpp, *offset, SEEK_SET);
+  printf("Offset set to: %ld\n", *offset);
+  fread(&data, 1, 1, fpp);
+  printf("Data: %d\n", data);
+  *type = ((data & 0x70)>>4);
+  printf("Type: %d\n", *type);
+  length |= data & 0x0F;
+  while ((data & 0x80) && fread(&data, 1, 1, fpp)!=-1)
+  {
+    length |= (unsigned long long)(data & 0x7F) << bitshift;
+    bitshift += 7; // (*offset)++;
+  }
+  printf("Length: %llu\n", length);
+
+  return length;
+}
+
+//   ToDo: borrowed from int inf(FILE *source, FILE *dest) in
+//   zpipe.c: example of proper use of zlib's inflate() and deflate()
+//   Not copyrighted -- provided to the public domain
+//   Version 1.4  11 December 2005  Mark Adler */
+#define CHUNK 4096
+int inf(FILE *source, char *dest) //modified signature to ease use
+{
+    int ret;
+    char *position = dest;
+    unsigned have;
+    z_stream strm;
+    unsigned char in[CHUNK];
+    unsigned char out[CHUNK];
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    strm.avail_in = 0;
+    strm.next_in = Z_NULL;
+    ret = inflateInit(&strm);
+    if (ret != Z_OK) return ret;
+
+    // decompress until deflate stream ends or end of file
+    do {
+
+        strm.avail_in = fread(in, 1, CHUNK, source);
+        if (ferror(source)) {
+            (void)inflateEnd(&strm);
+
+            return Z_ERRNO;
+        }
+        if (strm.avail_in == 0)
+            break;
+        strm.next_in = in;
+
+
+        // run inflate() on input until output buffer not full
+        do {
+
+            strm.avail_out = CHUNK;
+            strm.next_out = out;
+
+            ret = inflate(&strm, Z_NO_FLUSH);
+            //assert(ret != Z_STREAM_ERROR);  // state not clobbered
+            switch (ret) {
+            case Z_NEED_DICT:
+                ret = Z_DATA_ERROR;     // and fall through
+            case Z_DATA_ERROR:
+            case Z_MEM_ERROR:
+                (void)inflateEnd(&strm);
+
+                return ret;
+            }
+
+            have = CHUNK - strm.avail_out;
+	    memcpy(position, out, have); //added to original
+            position += have; //added to original
+            //if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
+            //    (void)inflateEnd(&strm);
+            //    return Z_ERRNO;
+            //}
+        } while (strm.avail_out == 0);
+       // done when inflate() says it's done
+    } while (ret != Z_STREAM_END);
+    // modified from zpipe.c to set FP to end of zlib object
+    fseek(source, ftell(source)-strm.avail_in, SEEK_SET);
+    // clean up and return
+    (void)inflateEnd(&strm);
+
+    return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
+}
+
+//https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L72
+//Set object to the index after adding prefix, calculating the hash and finding the position
+long set_object(struct IndexV2 *idx, int type, char *o, unsigned count,
+  unsigned ofs)
+{
+// TODO: Too many allocs in here 1) to concat the search string for hashing
+// 2) to insert into the array (can be reduce to a single malloc in fetch as
+// the pack header contains the number of objects in pack
+  char *c, *p = "", *h = xmalloc(20); //composition,prefix,hash
+  long pos = 0;
+
+  printf("Alloc... ");
+  //append a object prefix based on its type (not included in packfile)
+  switch(type) {
+    case 1: p = xmprintf("commit %d", count); break; //count is used as o can contain \0 in the  string
+    case 2: p = xmprintf("tree %d", count); break;
+    case 3: p = xmprintf("blob %d", count); break;
+    case 4: p = xmprintf("tag %d", count); break;
+    case 6: printf("REF_DELTA"); break; //not expected in fetch packs as fetch packs are self-containing
+    case 7: printf("OBJ_DELTA\n"); break;
+  }
+  c = xmalloc(strlen(p)+count+2);
+  memcpy(c, p, strlen(p)+1);
+  memcpy(c+strlen(p)+1, o, count+1);
+  h = SHA1(c, strlen(p)+count+1, h); //ToDo: borrowed from OpenSSL to not to pipe or refactor SHA1SUM in toybox
+  printf("..Binary search\n");
+  for (int j = 0; j<20; j++) printf("%02x", h[j]); //find insert position
+  pos = bsearchpos(h, idx->sha1[0], idx->fot[255], 20);
+  printf("\n..Insert pos %ld\n", pos);
+  printf("..Preloop\n");
+
+  //adjust of fanout table https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L204
+  for (int i = h[0]; i<=255; i++) idx->fot[i] += 1;
+  printf("Post loop\n");
+  printf("Resize sha1 array..idx->fot[255]%d\n", idx->fot[255]); //Memory management for insert
+  //TODO:Could be also a single malloc at gitfetch based on the nbr of objects in pack
+
+  //Did not fix the TODO yet, because set_object could be reused for other commands adding single objects to the index
+  idx->sha1 = realloc(idx->sha1, (idx->fot[255]+1)*20*sizeof(char));
+  printf("Mem copy sha1 array..sizeof(idx->sha1)%zu\n", sizeof(idx->sha1));
+  memmove(&idx->sha1[pos+1], &idx->sha1[pos], (idx->fot[255]-pos)*20*sizeof(char));
+  printf("Resize offset\n");
+  idx->offset = realloc(idx->offset, (idx->fot[255]+1)*sizeof(unsigned));
+  printf("Mem copy offset\n");
+  memmove(&idx->offset[pos+1], &idx->offset[pos], sizeof(unsigned)*(idx->fot[255]-pos));
+  printf("Set offset value\n");
+  memcpy(&idx->sha1[pos], h, 20); //insert SHA1
+  idx->offset[pos] = ofs; //insert offset of SHA1
+  //ToDo: id->crc[idx->fot[h[0]]]=;
+  printf("Write object\n");
+  free(h);
+  free(c);
+
+  return ofs;
+}
+
+//init a git repository in a given directory name
+static void gitinit(char *name)
+{
+  //For git clone actually only refs and object/pack are needed
+  if (mkdir(name, 0755)!=0){
+    //I create the others for a git compliant folder structure
+    mkdir(xmprintf("%s%s", name, "/.git"), 0755);
+    mkdir(xmprintf("%s%s", name, "/.git/objects"), 0755);
+    mkdir(xmprintf("%s%s", name, "/.git/objects/pack"), 0755);
+    mkdir(xmprintf("%s%s", name, "/.git/branches"), 0755);
+    mkdir(xmprintf("%s%s", name, "/.git/hooks"), 0755); //hook files skipped as implementations does not support hooks
+    mkdir(xmprintf("%s%s", name, "/.git/info"), 0755);
+    mkdir(xmprintf("%s%s", name, "/.git/objects/info"), 0755);
+    mkdir(xmprintf("%s%s", name, "/.git/refs"), 0755);
+    mkdir(xmprintf("%s%s", name, "/.git/heads"), 0755);
+    mkdir(xmprintf("%s%s", name, "/.git/tags"), 0755);
+    xcreate(xmprintf("%s%s", name, "/.git/config"), O_CREAT, 0644);
+    xcreate(xmprintf("%s%s", name, "/.git/description"), O_CREAT, 0644);
+    xcreate(xmprintf("%s%s", name, "/.git/HEAD"), O_CREAT, 0644);
+    xcreate(xmprintf("%s%s", name, "/.git/info/exclude"), O_CREAT, 0644);
+  }
+}
+
+//set basic configuration and add remote URL
+static void gitremote(char *url)
+{
+  if (access(".git/config", F_OK)!=0) {
+    FILE *fp = fopen(".git/config", "wb");
+
+    fwrite("[core]\n", 1, 7, fp);
+    fwrite("\trepositoryformatversion = 0\n", 1, 29, fp);
+    fwrite("\tfilemode = false\n", 1, 18, fp);
+    fwrite("\tbare = false\n", 1, 14, fp);
+    fwrite("\tlogallrefupdates = true\n", 1, 25, fp);
+    fwrite("\tsymlinks = false\n", 1, 18, fp);
+    fwrite("\tignorecase = true\n", 1, 19, fp);
+    fwrite("[remote \"origin\"]\n", 1, 18, fp);
+    fwrite(xmprintf("\turl = %s/refs\n", TT.url), 1, strlen(TT.url)+13, fp);
+    fwrite("\tfetch = +ref/heads/*:refs/remotes/origin/*\n", 1, 44, fp);
+    fclose(fp);
+  }
+}
+
+// this is most likely still buggy and create a late observable heap overflow larger deltafied repos
+// https://stackoverflow.com/a/14303988
+// resolve deltafied objects in the pack file, see URL in comments for further explainations
+char *resolve_delta(char *s, char *d, long dsize, unsigned *count)
+{
+  long pos = 0, bitshift = 0;
+  //https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L113
+  // Skipping source size; did not find out why it is  on the delta header as the source object header contains it too; maybe misunderstood and this makes things buggy, but I dont need it here
+  while ((d[pos] & 0x80)) pos++;
+  pos++; //fixes https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L114
+  *count = 0;
+  bitshift = 0;
+  while ((d[pos] & 0x80)) { //reading target_size from header
+    *count |= (unsigned long long)(d[pos++]& 0x7F) << bitshift;
+    bitshift += 7; // (*offset)++;
+  }
+
+  *count |= (unsigned long long)(d[pos++]& 0x7F) << bitshift;
+  printf("Target Count %d:\n", *count);
+  char *t = xmalloc(*count+1);
+  *count = 0;
+  while (pos<dsize) {
+    int i = 0, j = 1;
+    unsigned offset = 0, size = 0;
+
+    if ((d[pos]&0x80)) {//https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L128
+    //https://stackoverflow.com/a/14303988
+      printf("Case 1\n");
+      while (i<4) {
+        if (d[pos]&(1<<i)) {
+          offset |= d[pos+j]<<(i*8);
+          j++;
+        }
+        i++;
+      }
+      while (i<7) {
+        if (d[pos]&(1<<i)) {
+          size |= d[pos+j]<<(i*8);
+          j++;
+        }
+        i++;
+      }
+
+      // packfomat: size zero is automatically converted to 0x10000.
+      // https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L156
+      if (size==0) size = 0x10000;
+      memcpy(t+*count, s+offset, size);
+      //t[size] = '\0';
+      pos += j;
+      printf("Pos\n");
+    } else {
+      //https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L158
+    printf("Case 0\n");
+      size = d[pos++]; //incrememt
+      memcpy(t+*count, d+pos, size);
+      pos += size;
+    }
+    *count += size;
+
+    printf("Target: \n");
+  }
+  free(s);
+  free(d);
+
+  return t;
+}
+
+//unpack object (,resolve deltafied objects recursively) and return the unpacked object
+char *unpack_object(FILE *fpp, struct IndexV2 *i, long offset, unsigned *count,
+  int *type)
+{
+  unsigned dcount = unpack(fpp, type, &offset);
+  char *object = xmalloc(dcount);
+
+  object[*count] = '\0';
+  printf("Count: %d \n", *count);
+// see OBJ_REF_DELTA here https://yqintl.alicdn.com/eef7fe4f22cc97912cee011c99d3fe5821ae9e88.png
+  if (*type==7) {
+      char *h = xmalloc(20);
+
+      fread(h, 20, 1, fpp); //fseek(fpp, 20, SEEK_CUR);
+      printf("Read base object\n");
+      for (int j = 0; j<20; j++) printf("%02x", h[j]);
+      printf("\n");
+      inf(fpp, object); //TO CHECK IF INF OR PLAIN TEXT:
+      long toffset = ftell(fpp); //save original file offset
+      char *source = unpack_object(fpp, i, get_index(i, h), count, type);
+      printf("Inflate delta data\n");
+      fseek(fpp, toffset, SEEK_SET); //return to original file offset
+      printf("Resolve delta data\n");
+      free(h);//recursion due to https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L58
+      return resolve_delta(source, object, dcount, count);
+    } else {
+      printf("Type Else:\n");
+      inf(fpp, object);
+      *count = dcount;
+      printf("Type Else end:\n");
+      //printf("Unpacked Object: %s\n", object);
+
+      return object;
+    }
+}
+
+//make 20byte SHA1 hash from 40 byte SHA1 string
+char *txtoh(char *p)
+{
+  //TODO: Dont like the malloc here, but did not find a solution to sscanf into p again
+  char *h = xmalloc(41);
+
+  for (int c = 0; c<20; c++) {
+    sscanf(&p[2*c], "%2hhx", &(h[c]));
+  }
+  h[20] = 0;
+  printf("return");
+
+  return h;
+}
+
+//traveres the commit tree for checkout
+void write_children(char *hash, char *path, FILE *fpp)
+{
+  FILE *fc;
+  char *object;
+  int type;
+  long offset;
+  unsigned count=0;
+
+  printf("seek index\n");
+
+  offset = get_index(TT.i, hash);
+  printf("Found index: %ld\n", offset);
+  printf("read object\n");
+  object = unpack_object(fpp, TT.i, offset, &count, &type);
+  printf("%s\n", object);
+  printf("Type %d\n", type);
+  if (type==1) { //at commit object
+    memcpy(hash, object+5, 40);
+    write_children(txtoh(hash), path, fpp);
+  } else if (type==2) { //at tree object https://stackoverflow.com/a/21599232
+    char *hs, *name;
+    int pos = 0;
+
+    printf("process folder %s\n", path);
+    while (pos<count){
+      //find position where the next hash starts
+      hs = object+pos;
+      printf("Object+pos: %s\n", hs);
+      // memcpy(mode, hs+2, 3)//TODO:String to umask
+      if (*hs=='1') { //tree object reference is a file
+        // concat file name
+        name = *path ? xmprintf("%s/%s", path, hs+7) : hs+7;
+        printf("prepare file %s\n", name);
+      } else { //tree object reference is a folder
+        // concat folder name
+        name = *path ? xmprintf("%s/%s", path, hs+6) : hs+6;
+        printf("create folder %s\n", name);
+        mkdir(name, 0755); //TODO: umask
+      }
+      hs += strlen(hs)+1;
+      memcpy(hash, hs, 20);
+      write_children(hash, name, fpp);
+      pos = hs-object+20;
+      printf("Position/count for %s: %d/%u\n", path, pos, count);
+    }
+    printf("**EXIT WHILE**\n");
+  } else { //at blob/file object
+    printf("process file %s\n", path);
+    fc = fopen(path, "w");
+    printf("process opened \n");
+    fputs(object, fc); //TODO:Not sure if length might be an issue here
+    printf("process file written\n");
+    fclose(fc);
+  }
+  free(object);
+  printf("Child: %s done\n", path);
+}
+
+//fetches the meta data from the remote repository,requests a pack file for the remote master head,
+//unpacks all objects and set objects to the index
+static void gitfetch(void)
+{
+  printf("refs\n");
+
+  // TODO:I use herein after two temp files for fetch which git does not offer
+  // to 1) avoid a rewrite and 2) messing up the repo files while testing
+
+  // TODO: Refactor wget into lib
+  xrun((char *[]){"wget", "-O", ".git/refs/temp.refs",
+      "https://github.com/landley/toybox/info/refs?service=git-upload-pack",
+      0});
+  //char h[] = "8cf1722f0fde510ea81d13b31bde1e48917a0306";
+  //TODO: Replace static testing hash and uncomment the following line if rare delta resolve /?heap overflow? bug was found
+  FILE *fpr = fopen(".git/refs/temp.refs", "r");
+  char *h;
+  size_t l = 0;
+
+  getline(&h,&l,fpr);
+  getline(&h,&l,fpr);
+  getline(&h,&l,fpr);
+  getline(&h,&l,fpr);
+  fclose(fpr);
+  strcpy(h,&h[4]);
+  h[40] = 0;
+  printf("Master HEAD hash: %s\n",h);
+  //TODO: Persist hash to /refs/master/HEAD
+  printf("pack\n");
+  xrun((char *[]){"toybox", "wget", "-O", ".git/objects/pack/temp.pack", "-p", xmprintf("$'0032want %s\n00000009done\n'", h), "https://github.com/landley/toybox/git-upload-pack", 0});
+  //TODO: does not skip 0008NAK  printf("init\n");
+  FILE *fpp;
+  printf("openpack\n");
+  fpp = fopen(".git/objects/pack/temp.pack", "r");
+  printf("read index\n");
+  read_index(TT.i); //init index with out reading
+  printf("init\n");
+  unsigned ocount = 0, count;
+  int type;
+  char *object;
+
+  printf("skip header\n");
+  long offset = 12+8; //8byte from the wget post response are skipped too
+  fseek(fpp, 8+8, SEEK_SET); //header check skipped //header check skipped https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L37
+  printf("read count\n");
+  fread(&ocount, 4, 1, fpp);
+  ocount = ntohl(ocount); //https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt#L46
+  printf("Count: %d ..Loop pack\n", ocount);
+  for (int j = 0; j<ocount; j++){
+    printf("Read object %d\n", j);
+    count = 0;
+    object = unpack_object(fpp, TT.i, offset, &count, &type);
+    printf("Count: %d Offset: %ld  ..Set object\n", count, offset);
+    set_object(TT.i, type, object, count, offset);
+
+    free(object);
+
+    printf("Adjust offset\n");
+    offset = ftell(fpp); //adjust offset to new file position
+    printf("Adjusted offset to: %ld\n", offset);
+  }
+
+  //TODO: Final pack checksum not calculated and checked
+  fclose(fpp);
+}
+
+//Checkout HEAD to the  working directory by recursing write_children
+//TODO: Replase static hashes with hash read from refs/<branch>/head
+static void gitcheckout(char *name)
+{
+
+  FILE *fpp;
+  //FILE *fh;
+
+  printf("Find branch for checkout\n");
+  //fh = fopen(xmprintf(".git/ref/heads/%s", name ? "master" : name), "r"); //TODO: Checkout master as in ref/heads
+  printf("Read head\n");
+  //hf[fread(&hf, 40, 1, fh)] = '\0';
+  //fclose(fh);
+  printf("Close heads and read pack\n");
+  fpp = fopen(".git/objects/pack/temp.pack", "r");
+  printf("set signature\n");
+  char *p = "52fb04274b3491fdfe91b2e5acc23dc3f3064a86"; //static hashes for testing toybox 0.0.1";
+  //char *p = "c555a0ca46e75097596274bf5e634127015aa144"; //static hashes for testing 0.0.2";
+  //char *p = "4307a7b07cec4ad8cbab47a29ba941f8cb041812"; //static hashes for testing 0.0.3";
+  //char *p = "3632d5d8fe05d14da983e37c7cd34db0769e6238"; //static hashes for testing 0.0.4";
+  //char *p = "8cf1722f0fde510ea81d13b31bde1e48917a0306"; //3604ba4f42c3d83e2b14f6d0f423a33a3a8706c3";
+  printf("enter tree root\n");
+  write_children(txtoh(p), "", fpp);
+  fclose(fpp);
+}
+
+void gitclone_main(void)
+{
+  TT.url = xstrdup(toys.optargs[0]);
+  if (strend(TT.url, ".git")) TT.url[strlen(TT.url)-4] = '\0';
+  TT.name = strrchr(TT.url, '/')+1;
+  gitinit(TT.name);
+  chdir(TT.name);
+  TT.i = malloc(sizeof(struct IndexV2));
+  gitremote(TT.url);
+  gitfetch();
+  gitcheckout("master");
+  chdir("..");
+}
+
+#define FOR_gitinit
+#include "generated/flags.h"
+
+void gitinit_main(void)
+{
+  gitinit(xstrdup(toys.optargs[0]));
+}
+
+#define FOR_gitremote
+
+void gitremote_main(void)
+{
+  TT.url = xstrdup(toys.optargs[0]);
+  if (strend(TT.url, ".git")) TT.url[strlen(TT.url)-4] = '\0';
+  gitremote(TT.url);
+}
+
+#define FOR_gitinit
+
+void gitfetch_main(void)
+{
+  gitfetch();
+}
+
+#define FOR_gitcheckout
+
+void gitcheckout_main(void)
+{
+  gitcheckout(xstrdup(toys.optargs[0]));
+}
+
+// Command to wget refs and pack file using toybox wget to place them manually into the repository
+// ./toybox wget -O - -d https://github.com/landley/toybox/info/refs?service=git-upload-pack | less
+
+// ./toybox wget -O pack.dat -d -p $'0032want 8cf1722f0fde510ea81d13b31bde1e48917a0306\n00000009done\n' https://github.com/landley/toybox/git-upload-pack
diff --git a/toys/pending/init.c b/toys/pending/init.c
index 05afb71..9f4e7ba 100644
--- a/toys/pending/init.c
+++ b/toys/pending/init.c
@@ -124,6 +124,7 @@
 {
   char *line = 0;
   size_t allocated_length = 0;
+  ssize_t line_length = 0;
   int line_number = 0;
   char *act_name = "sysinit\0wait\0once\0respawn\0askfirst\0ctrlaltdel\0"
                     "shutdown\0restart\0";
@@ -136,10 +137,11 @@
     return;
   }
 
-  while (getline(&line, &allocated_length, fp) > 0) {
+  while ((line_length = getline(&line, &allocated_length, fp)) > 0) {
     char *p = line, *x, *tty_name = 0, *command = 0, *extracted_token, *tmp;
     int action = 0, token_count = 0, i;
 
+    if (p[line_length - 1] == '\n') p[line_length - 1] = '\0';
     if ((x = strchr(p, '#'))) *x = '\0';
     line_number++;
     action = 0;
diff --git a/toys/pending/lsof.c b/toys/pending/lsof.c
index e4b5311..2748854 100644
--- a/toys/pending/lsof.c
+++ b/toys/pending/lsof.c
@@ -42,8 +42,7 @@
   char *name, fd[8], rw, locks, type[10], device[32], size_off[32], node[32];
 
   // For filtering.
-  dev_t st_dev;
-  ino_t st_ino;
+  struct dev_ino di;
 };
 
 static void print_info(void *data)
@@ -55,13 +54,11 @@
     int i;
 
     for (i = 0; i<toys.optc; i++)
-      if (TT.sought_files[i].st_dev==fi->st_dev)
-        if (TT.sought_files[i].st_ino==fi->st_ino) break;
-
+      if (same_dev_ino(TT.sought_files+i, &fi->di)) break;
     if (i==toys.optc) return;
   }
 
-  if (toys.optflags&FLAG_t) {
+  if (FLAG(t)) {
     if (fi->pi.pid != TT.last_shown_pid)
       printf("%d\n", TT.last_shown_pid = fi->pi.pid);
   } else {
@@ -92,8 +89,7 @@
   unsigned flags;
 
   snprintf(toybuf, sizeof(toybuf), "/proc/%d/fdinfo/%s", fi->pi.pid, fi->fd);
-  fp = fopen(toybuf, "r");
-  if (!fp) return;
+  if (!(fp = fopen(toybuf, "r"))) return;
 
   if (fscanf(fp, "pos: %lld flags: %o", &pos, &flags) == 2) {
     flags &= O_ACCMODE;
@@ -130,7 +126,7 @@
   struct file_info *fi = xzalloc(sizeof(struct file_info));
 
   dlist_add_nomalloc(&TT.all_sockets, (struct double_list *)fi);
-  fi->st_ino = inode;
+  fi->di.ino = inode;
   strcpy(fi->type, type);
   return fi;
 }
@@ -231,9 +227,9 @@
   void* list = TT.all_sockets;
 
   while (list) {
-    struct file_info *s = (struct file_info*) llist_pop(&list);
+    struct file_info *s = (struct file_info *)llist_pop(&list);
 
-    if (s->st_ino == inode) {
+    if (s->di.ino == inode) {
       fi->name = s->name ? strdup(s->name) : NULL;
       strcpy(fi->type, s->type);
       return 1;
@@ -282,8 +278,8 @@
   snprintf(fi->node, sizeof(fi->node), "%ld", (long)sb.st_ino);
 
   // Stash st_dev and st_ino for filtering.
-  fi->st_dev = sb.st_dev;
-  fi->st_ino = sb.st_ino;
+  fi->di.dev = sb.st_dev;
+  fi->di.ino = sb.st_ino;
 }
 
 struct file_info *new_file_info(struct proc_info *pi, const char *fd)
diff --git a/toys/pending/mke2fs.c b/toys/pending/mke2fs.c
index ee0a5b1..0741157 100644
--- a/toys/pending/mke2fs.c
+++ b/toys/pending/mke2fs.c
@@ -342,9 +342,7 @@
       // Look for other copies of current node
       current->st.st_nlink = 0;
       for (that = tree; that; that = treenext(that)) {
-        if (current->st.st_ino == that->st.st_ino &&
-          current->st.st_dev == that->st.st_dev)
-        {
+        if (same_file(current, that)) {
           current->st.st_nlink++;
           current->st.st_ino = inode;
         }
diff --git a/toys/pending/modprobe.c b/toys/pending/modprobe.c
index 45f8ea2..133d878 100644
--- a/toys/pending/modprobe.c
+++ b/toys/pending/modprobe.c
@@ -444,7 +444,7 @@
     }
     // none of above is true insert the module.
     errno = 0;
-    rc = ins_mod(fn, options);
+    rc = ins_mod(fn, options ? : "");
     if (FLAG(v))
       printf("loaded %s '%s': %s\n", fn, options, strerror(errno));
     if (errno == EEXIST) rc = 0;
@@ -489,15 +489,15 @@
   }
 
   // Read /proc/modules to get loaded modules.
-  fs = xfopen("/proc/modules", "r");
-  
-  while (read_line(fs, &procline) > 0) {
+  fs = fopen("/proc/modules", "r");
+
+  while (fs && read_line(fs, &procline) > 0) {
     *strchr(procline, ' ') = 0;
     get_mod(procline, 1)->flags = MOD_ALOADED;
     free(procline);
     procline = NULL;
   }
-  fclose(fs);
+  if (fs) fclose(fs);
   if (FLAG(a) || FLAG(r)) for (; *argv; argv++) add_mod(*argv);
   else {
     add_mod(*argv);
diff --git a/toys/pending/sh.c b/toys/pending/sh.c
index 8f45c17..2bdf64a 100644
--- a/toys/pending/sh.c
+++ b/toys/pending/sh.c
@@ -10,6 +10,9 @@
  * and http://opengroup.org/onlinepubs/9699919799/utilities/sh.html
  *
  * deviations from posix: don't care about $LANG or $LC_ALL
+ * deviations from bash:
+ *   redirect+expansion in one pass so we can't report errors between them.
+ *   Trailing redirects error at runtime, not parse time.
 
  * builtins: alias bg command fc fg getopts jobs newgrp read umask unalias wait
  *          disown suspend source pushd popd dirs logout times trap cd hash exit
@@ -70,10 +73,62 @@
     usage: sh [-c command] [script]
 
     Command shell.  Runs a shell script, or reads input interactively
-    and responds to it.
+    and responds to it. Roughly compatible with "bash". Run "help" for
+    list of built-in commands.
 
     -c	command line to execute
     -i	interactive mode (default when STDIN is a tty)
+    -s	don't run script (args set $* parameters but read commands from stdin)
+
+    Command shells parse each line of input (prompting when interactive), perform
+    variable expansion and redirection, execute commands (spawning child processes
+    and background jobs), and perform flow control based on the return code.
+
+    Parsing:
+      syntax errors
+
+    Interactive prompts:
+      line continuation
+
+    Variable expansion:
+      Note: can cause syntax errors at runtime
+
+    Redirection:
+      HERE documents (parsing)
+      Pipelines (flow control and job control)
+
+    Running commands:
+      process state
+      builtins
+        cd [[ ]] (( ))
+        ! : [ # TODO: help for these?
+        true false help echo kill printf pwd test
+      child processes
+
+    Job control:
+      &    Background process
+      Ctrl-C kill process
+      Ctrl-Z suspend process
+      bg fg jobs kill
+
+    Flow control:
+    ;    End statement (same as newline)
+    &    Background process (returns true unless syntax error)
+    &&   If this fails, next command fails without running
+    ||   If this succeeds, next command succeeds without running
+    |    Pipelines! (Can of worms...)
+    for {name [in...]}|((;;)) do; BODY; done
+    if TEST; then BODY; fi
+    while TEST; do BODY; done
+    case a in X);; esac
+    [[ TEST ]]
+    ((MATH))
+
+    Job control:
+    &    Background process
+    Ctrl-C kill process
+    Ctrl-Z suspend process
+    bg fg jobs kill
 
 # These are here for the help text, they're not selectable and control nothing
 config CD
@@ -256,7 +311,7 @@
   long long SECONDS;
   char *isexec, *wcpat;
   unsigned options, jobcnt, LINENO;
-  int hfd, pid, bangpid, varslen, srclvl, recursion;
+  int hfd, pid, bangpid, srclvl, recursion;
 
   // Callable function array
   struct sh_function {
@@ -282,11 +337,11 @@
       long flags;
       char *str;
     } *vars;
-    long varslen, shift;
+    long varslen, varscap, shift, oldlineno;
 
     struct sh_function *func; // TODO wire this up
     struct sh_pipeline *pl;
-    char *ifs;
+    char *ifs, *omnom;
     struct sh_arg arg;
     struct arg_list *delete;
 
@@ -318,6 +373,10 @@
 
 // Prototype because $($($(blah))) nests, leading to run->parse->run loop
 int do_source(char *name, FILE *ff);
+// functions contain pipelines contain functions: prototype because loop
+static void free_pipeline(void *pipeline);
+// recalculate needs to get/set variables, but setvar_found calls recalculate
+static struct sh_vars *setvar(char *str);
 
 // ordered for greedy matching, so >&; becomes >& ; not > &;
 // making these const means I need to typecast the const away later to
@@ -338,7 +397,10 @@
 
 static void syntax_err(char *s)
 {
-  error_msg("syntax error: %s", s);
+  struct sh_fcall *ff = TT.ff;
+// TODO: script@line only for script not interactive.
+  for (ff = TT.ff; ff != TT.ff->prev; ff = ff->next) if (ff->omnom) break;
+  error_msg("syntax error '%s'@%u: %s", ff->omnom ? : "-c", TT.LINENO, s);
   toys.exitval = 2;
   if (!(TT.options&FLAG_i)) xexit();
 }
@@ -362,6 +424,13 @@
   closedir(X);
 }
 
+static char **nospace(char **ss)
+{
+  while (isspace(**ss)) ++*ss;
+
+  return ss;
+}
+
 // append to array with null terminator and realloc as necessary
 static void arg_add(struct sh_arg *arg, char *data)
 {
@@ -440,129 +509,6 @@
   return 0;
 }
 
-// Append variable to ff->vars, returning *struct. Does not check duplicates.
-static struct sh_vars *addvar(char *s, struct sh_fcall *ff)
-{
-  if (!(ff->varslen&31))
-    ff->vars = xrealloc(ff->vars, (ff->varslen+32)*sizeof(*ff->vars));
-  if (!s) return ff->vars;
-  ff->vars[ff->varslen].flags = 0;
-  ff->vars[ff->varslen].str = s;
-
-  return ff->vars+ff->varslen++;
-}
-
-static char **nospace(char **ss)
-{
-  while (isspace(**ss)) ++*ss;
-
-  return ss;
-}
-
-/*
-15L ( [ . -> ++ --
-14R (all prefix operators)
-++ -- + - ! ~ (typecast) * & sizeof
-13L * / %
-12L + -
-11L << >>
-10L < <= > >=
-9L == !=
-8L & (bitwise)
-7L ^ (xor)
-6L |
-5L &&
-4L ||
-3R ? :
-2R (assignments) = += -= *= /= %= &= ^= |= <<= >>=
-1L ,
-
-*/
-
-// Recursively calculate string into dd, returns 0 if failed, ss = error point
-static int recalculate(long long *dd, char **ss, int lvl)
-{
-  long long ee, ff;
-  char cc = **nospace(ss);
-
-  // TODO: assignable (variable)
-  // Always start handling unary prefixes, parenthetical blocks, and constants
-  if (cc=='+' || cc=='-') {
-    ++*ss;
-    if (!recalculate(dd, ss, 1)) return 0;
-    if (cc=='-') *dd = -*dd;
-  } else if (cc=='(') {
-    ++*ss;
-    if (!recalculate(dd, ss, 1)) return 0;
-    if (**ss!=')') return 0;
-    else ++*ss;
-  } else if (isdigit(cc)) *dd = strtoll(*ss, ss, 0); //TODO overflow?
-  else if (!lvl && (!cc || cc==')')) {
-    *dd = 0;
-    return 1;
-  } else return 0;
-
-  // x^y binds first
-  if (lvl<4) while (strstart(nospace(ss), "**")) {
-    if (!recalculate(&ee, ss, 4)) return 0;
-    if (ee<0) perror_msg("** < 0");
-    for (ff = *dd, *dd = 1; ee; ee--) *dd *= ff;
-  }
-
-  // w*x/y%z bind next
-  if (lvl<3) while ((cc = **nospace(ss))) {
-    if (cc=='*' || cc=='/' || cc=='%') {
-      ++*ss;
-      if (!recalculate(&ee, ss, 3)) return 0;
-      if (cc=='*') *dd *= ee;
-      else if (cc=='%') *dd %= ee;
-      else if (!ee) {
-        perror_msg("/0");
-        return 0;
-      } else *dd /= ee;
-    } else break;
-  }
-
-  // x+y-z
-  if (lvl<2) while ((cc = **nospace(ss))) {
-    if (cc=='+' || cc=='-') {
-      ++*ss;
-      if (!recalculate(&ee, ss, 2)) return 0;
-      if (cc=='+') *dd += ee;
-      else *dd -= ee;
-    } else break;
-  }
-  nospace(ss);
-
-  return 1;
-}
-
-static int calculate(long long *ll, char *equation)
-{
-  char *ss = equation;
-
-  // TODO: error_msg->sherror_msg() with LINENO for scripts
-  if (!recalculate(ll, &ss, 0) || *ss) {
-    perror_msg("bad math: %s @ %d", equation, (int)(ss-equation));
-
-    return 0;
-  }
-
-  return 1;
-}
-
-// Return length of utf8 char @s fitting in len, writing value into *cc
-int getutf8(char *s, int len, int *cc)
-{
-  unsigned wc;
-
-  if (len<0) wc = len = 0;
-  else if (1>(len = utf8towc(&wc, s, len))) wc = *s, len = 1;
-  if (cc) *cc = wc;
-
-  return len;
-}
-
 // get value of variable starting at s.
 static char *getvar(char *s)
 {
@@ -592,6 +538,287 @@
   return varend(var->str)+1;
 }
 
+// Append variable to ff->vars, returning *struct. Does not check duplicates.
+static struct sh_vars *addvar(char *s, struct sh_fcall *ff)
+{
+  if (ff->varslen == ff->varscap && !(ff->varslen&31)) {
+    ff->varscap += 32;
+    ff->vars = xrealloc(ff->vars, (ff->varscap)*sizeof(*ff->vars));
+  }
+  if (!s) return ff->vars;
+  ff->vars[ff->varslen].flags = 0;
+  ff->vars[ff->varslen].str = s;
+
+  return ff->vars+ff->varslen++;
+}
+
+// Recursively calculate string into dd, returns 0 if failed, ss = error point
+// Recursion resolves operators of lower priority level to a value
+// Loops through operators at same priority
+#define NO_ASSIGN 128
+static int recalculate(long long *dd, char **ss, int lvl)
+{
+  long long ee, ff;
+  char *var = 0, *val, cc = **nospace(ss);
+  int ii, noa = lvl&NO_ASSIGN;
+  lvl &= NO_ASSIGN-1;
+
+  // Unary prefixes can only occur at the start of a parse context
+  if (cc=='!' || cc=='~') {
+    ++*ss;
+    if (!recalculate(dd, ss, noa|15)) return 0;
+    *dd = (cc=='!') ? !*dd : ~*dd;
+  } else if (cc=='+' || cc=='-') {
+    // Is this actually preincrement/decrement? (Requires assignable var.)
+    if (*++*ss==cc) {
+      val = (*ss)++;
+      nospace(ss);
+      if (*ss==(var = varend(*ss))) {
+        *ss = val;
+        var = 0;
+      }
+    }
+    if (!var) {
+      if (!recalculate(dd, ss, noa|15)) return 0;
+      if (cc=='-') *dd = -*dd;
+    }
+  } else if (cc=='(') {
+    ++*ss;
+    if (!recalculate(dd, ss, noa|1)) return 0;
+    if (**ss!=')') return 0;
+    else ++*ss;
+  } else if (isdigit(cc)) {
+    *dd = strtoll(*ss, ss, 0);
+    if (**ss=='#') {
+      if (!*++*ss || isspace(**ss) || ispunct(**ss)) return 0;
+      *dd = strtoll(val = *ss, ss, *dd);
+      if (val == *ss) return 0;
+    }
+  } else if ((var = varend(*ss))==*ss) {
+    // At lvl 0 "" is ok, anything higher needs a non-empty equation
+    if (lvl || (cc && cc!=')')) return 0;
+    *dd = 0;
+
+    return 1;
+  }
+
+  // If we got a variable, evaluate its contents to set *dd
+  if (var) {
+    // Recursively evaluate, catching x=y; y=x; echo $((x))
+    if (TT.recursion++ == 50+200*CFG_TOYBOX_FORK) {
+      perror_msg("recursive occlusion");
+      --TT.recursion;
+
+      return 0;
+    }
+    val = getvar(var = *ss) ? : "";
+    ii = recalculate(dd, &val, noa);
+    TT.recursion--;
+    if (!ii) return 0;
+    if (*val) {
+      perror_msg("bad math: %s @ %d", var, (int)(val-var));
+
+      return 0;
+    }
+    val = *ss = varend(var);
+
+    // Operators that assign to a varible must be adjacent to one:
+
+    // Handle preincrement/predecrement (only gets here if var set before else)
+    if (cc=='+' || cc=='-') {
+      if (cc=='+') ee = ++*dd;
+      else ee = --*dd;
+    } else cc = 0;
+
+    // handle postinc/postdec
+    if ((**nospace(ss)=='+' || **ss=='-') && (*ss)[1]==**ss) {
+      ee = ((cc = **ss)=='+') ? 1+*dd : -1+*dd;
+      *ss += 2;
+
+    // Assignment operators: = *= /= %= += -= <<= >>= &= ^= |=
+    } else if (lvl<=2 && (*ss)[ii = (-1 != stridx("*/%+-", **ss))
+               +2*!smemcmp(*ss, "<<", 2)+2*!smemcmp(*ss, ">>", 2)]=='=')
+    {
+      // TODO: assignments are lower priority BUT must go after variable,
+      // come up with precedence checking tests?
+      cc = **ss;
+      *ss += ii+1;
+      if (!recalculate(&ee, ss, noa|1)) return 0; // TODO lvl instead of 1?
+      if (cc=='*') *dd *= ee;
+      else if (cc=='+') *dd += ee;
+      else if (cc=='-') *dd -= ee;
+      else if (cc=='<') *dd <<= ee;
+      else if (cc=='>') *dd >>= ee;
+      else if (cc=='&') *dd &= ee;
+      else if (cc=='^') *dd ^= ee;
+      else if (cc=='|') *dd |= ee;
+      else if (!cc) *dd = ee;
+      else if (!ee) {
+        perror_msg("%c0", cc);
+
+        return 0;
+      } else if (cc=='/') *dd /= ee;
+      else if (cc=='%') *dd %= ee;
+      ee = *dd;
+    }
+    if (cc && !noa) setvar(xmprintf("%.*s=%lld", (int)(val-var), var, ee));
+  }
+
+  // x**y binds first
+  if (lvl<=14) while (strstart(nospace(ss), "**")) {
+    if (!recalculate(&ee, ss, noa|15)) return 0;
+    if (ee<0) perror_msg("** < 0");
+    for (ff = *dd, *dd = 1; ee; ee--) *dd *= ff;
+  }
+
+  // w*x/y%z bind next
+  if (lvl<=13) while ((cc = **nospace(ss)) && strchr("*/%", cc)) {
+    ++*ss;
+    if (!recalculate(&ee, ss, noa|14)) return 0;
+    if (cc=='*') *dd *= ee;
+    else if (!ee) {
+      perror_msg("%c0", cc);
+
+      return 0;
+    } else if (cc=='%') *dd %= ee;
+    else *dd /= ee;
+  }
+
+  // x+y-z
+  if (lvl<=12) while ((cc = **nospace(ss)) && strchr("+-", cc)) {
+    ++*ss;
+    if (!recalculate(&ee, ss, noa|13)) return 0;
+    if (cc=='+') *dd += ee;
+    else *dd -= ee;
+  }
+
+  // x<<y >>
+
+  if (lvl<=11) while ((cc = **nospace(ss)) && strchr("<>", cc) && cc==(*ss)[1]){
+    *ss += 2;
+    if (!recalculate(&ee, ss, noa|12)) return 0;
+    if (cc == '<') *dd <<= ee;
+    else *dd >>= ee;
+  }
+
+  // x<y <= > >=
+  if (lvl<=10) while ((cc = **nospace(ss)) && strchr("<>", cc)) {
+    if ((ii = *++*ss=='=')) ++*ss;
+    if (!recalculate(&ee, ss, noa|11)) return 0;
+    if (cc=='<') *dd = ii ? (*dd<=ee) : (*dd<ee);
+    else *dd = ii ? (*dd>=ee) : (*dd>ee);
+  }
+
+  if (lvl<=9) while ((cc = **nospace(ss)) && strchr("=!", cc) && (*ss)[1]=='='){
+    *ss += 2;
+    if (!recalculate(&ee, ss, noa|10)) return 0;
+    *dd = (cc=='!') ? *dd != ee : *dd == ee;
+  }
+
+  if (lvl<=8) while (**nospace(ss)=='&' && (*ss)[1]!='&') {
+    ++*ss;
+    if (!recalculate(&ee, ss, noa|9)) return 0;
+    *dd &= ee;
+  }
+
+  if (lvl<=7) while (**nospace(ss)=='^') {
+    ++*ss;
+    if (!recalculate(&ee, ss, noa|8)) return 0;
+    *dd ^= ee;
+  }
+
+  if (lvl<=6) while (**nospace(ss)=='|' && (*ss)[1]!='|') {
+    ++*ss;
+    if (!recalculate(&ee, ss, noa|7)) return 0;
+    *dd |= ee;
+  }
+
+  if (lvl<=5) while (strstart(nospace(ss), "&&")) {
+    if (!recalculate(&ee, ss, noa|6|NO_ASSIGN*!*dd)) return 0;
+    *dd = *dd && ee;
+  }
+
+  if (lvl<=4) while (strstart(nospace(ss), "||")) {
+    if (!recalculate(&ee, ss, noa|5|NO_ASSIGN*!!*dd)) return 0;
+    *dd = *dd || ee;
+  }
+
+  // ? : slightly weird: recurses with lower priority instead of looping
+  // because a ? b ? c : d ? e : f : g == a ? (b ? c : (d ? e : f) : g)
+  if (lvl<=3) if (**nospace(ss)=='?') {
+    ++*ss;
+    if (**nospace(ss)==':' && *dd) ee = *dd;
+    else if (!recalculate(&ee, ss, noa|1|NO_ASSIGN*!*dd) || **nospace(ss)!=':')
+      return 0;
+    ++*ss;
+    if (!recalculate(&ff, ss, noa|1|NO_ASSIGN*!!*dd)) return 0;
+    *dd = *dd ? ee : ff;
+  }
+
+  // lvl<=2 assignment would go here, but handled above because variable
+
+  // , (slightly weird, replaces dd instead of modifying it via ee/ff)
+  if (lvl<=1) while (**nospace(ss)==',') {
+    ++*ss;
+    if (!recalculate(dd, ss, noa|2)) return 0;
+  }
+
+  return 1;
+}
+
+// Return length of utf8 char @s fitting in len, writing value into *cc
+static int getutf8(char *s, int len, int *cc)
+{
+  unsigned wc;
+
+  if (len<0) wc = len = 0;
+  else if (1>(len = utf8towc(&wc, s, len))) wc = *s, len = 1;
+  if (cc) *cc = wc;
+
+  return len;
+}
+
+// utf8 strchr: return wide char matched at wc from chrs, or 0 if not matched
+// if len, save length of next wc (whether or not it's in list)
+static int utf8chr(char *wc, char *chrs, int *len)
+{
+  unsigned wc1, wc2;
+  int ll;
+
+  if (len) *len = 1;
+  if (!*wc) return 0;
+  if (0<(ll = utf8towc(&wc1, wc, 99))) {
+    if (len) *len = ll;
+    while (*chrs) {
+      if(1>(ll = utf8towc(&wc2, chrs, 99))) chrs++;
+      else {
+        if (wc1 == wc2) return wc1;
+        chrs += ll;
+      }
+    }
+  }
+
+  return 0;
+}
+
+// return length of match found at this point (try is null terminated array)
+static int anystart(char *s, char **try)
+{
+  char *ss = s;
+
+  while (*try) if (strstart(&s, *try++)) return s-ss;
+
+  return 0;
+}
+
+// does this entire string match one of the strings in try[]
+static int anystr(char *s, char **try)
+{
+  while (*try) if (!strcmp(s, *try++)) return 1;
+
+  return 0;
+}
+
 // Update $IFS cache in function call stack after variable assignment
 static void cache_ifs(char *s, struct sh_fcall *ff)
 {
@@ -655,7 +882,13 @@
   // integer variables treat += differently
   ss = s+vlen+(s[vlen]=='+')+1;
   if (flags&VAR_INT) {
-    if (!calculate(&ll, ss)) goto bad;
+    sd = ss;
+    if (!recalculate(&ll, &sd, 0) || *sd) {
+      perror_msg("bad math: %s @ %d", ss, (int)(sd-ss));
+
+      goto bad;
+    }
+
     sprintf(buf, "%lld", ll);
     if (flags&VAR_MAGIC) {
       if (*s == 'S') {
@@ -704,16 +937,18 @@
   if (ss[*ss=='+']!='=') {
     error_msg("bad setvar %s\n", s);
     if (freeable) free(s);
+
     return 0;
   }
 
   // Add if necessary, set value, and remove again if we added but set failed
   if (!(was = vv = findvar(s, &ff))) (vv = addvar(s, ff))->flags = VAR_NOFREE;
-  if (!(vv = setvar_found(s, freeable, vv))) {
-    int ii = vv-ff->vars;
+  if (!setvar_found(s, freeable, vv)) {
+    if (!was) memmove(vv, vv+1, sizeof(ff->vars)*(--ff->varslen-(vv-ff->vars)));
 
-    if (!was) memmove(ff->vars+ii, ff->vars+ii+1, (ff->varslen--)-ii);
-  } else cache_ifs(vv->str, ff);
+    return 0;
+  }
+  cache_ifs(vv->str, ff);
 
   return vv;
 }
@@ -731,7 +966,7 @@
 {
   struct sh_fcall *ff;
   struct sh_vars *var = findvar(name, &ff);
-  int ii = var-ff->vars, len = varend(name)-name;
+  int len = varend(name)-name;
 
   if (!var || (var->flags&VAR_WHITEOUT)) return 0;
   if (var->flags&VAR_READONLY) error_msg("readonly %.*s", len, name);
@@ -744,7 +979,7 @@
     // free from global context
     } else {
       if (!(var->flags&VAR_NOFREE)) free(var->str);
-      memmove(ff->vars+ii, ff->vars+ii+1, (ff->varslen--)-ii);
+      memmove(var, var+1, sizeof(ff->vars)*(ff->varslen-(var-ff->vars)));
     }
     if (!strcmp(name, "IFS"))
       do ff->ifs = " \t\n"; while ((ff = ff->next) != TT.ff->prev);
@@ -817,26 +1052,8 @@
   return ss; 
 }
 
-// return length of match found at this point (try is null terminated array)
-static int anystart(char *s, char **try)
-{
-  char *ss = s;
-
-  while (*try) if (strstart(&s, *try++)) return s-ss;
-
-  return 0;
-}
-
-// does this entire string match one of the strings in try[]
-static int anystr(char *s, char **try)
-{
-  while (*try) if (!strcmp(s, *try++)) return 1;
-
-  return 0;
-}
-
-// return length of valid prefix that could go before redirect
-static int redir_prefix(char *word)
+// Skip past valid prefix that could go before redirect
+static char *skip_redir_prefix(char *word)
 {
   char *s = word;
 
@@ -845,7 +1062,7 @@
     else s = word;
   } else while (isdigit(*s)) s++;
 
-  return s-word;
+  return s;
 }
 
 // parse next word from command line. Returns end, or 0 if need continuation
@@ -857,7 +1074,7 @@
   char *end = start, *ss;
 
   // Handle redirections, <(), (( )) that only count at the start of word
-  ss = end + redir_prefix(end); // 123<<file- parses as 2 args: "123<<" "file-"
+  ss = skip_redir_prefix(end); // 123<<file- parses as 2 args: "123<<" "file-"
   if (strstart(&ss, "<(") || strstart(&ss, ">(")) {
     toybuf[quote++]=')';
     end = ss;
@@ -975,6 +1192,21 @@
   return 0;
 }
 
+// restore displaced filehandles, closing high filehandles they were copied to
+static void unredirect(int *urd)
+{
+  int *rr = urd+1, i;
+
+  if (!urd) return;
+
+  for (i = 0; i<*urd; i++, rr += 2) if (rr[0] != -1) {
+    // No idea what to do about fd exhaustion here, so Steinbach's Guideline.
+    dup2(rr[0], rr[1]);
+    close(rr[0]);
+  }
+  free(urd);
+}
+
 // TODO: waitpid(WNOHANG) to clean up zombies and catch background& ending
 static void subshell_callback(char **argv)
 {
@@ -1014,21 +1246,6 @@
 // TODO handle functions
 }
 
-// restore displaced filehandles, closing high filehandles they were copied to
-static void unredirect(int *urd)
-{
-  int *rr = urd+1, i;
-
-  if (!urd) return;
-
-  for (i = 0; i<*urd; i++, rr += 2) if (rr[0] != -1) {
-    // No idea what to do about fd exhaustion here, so Steinbach's Guideline.
-    dup2(rr[0], rr[1]);
-    close(rr[0]);
-  }
-  free(urd);
-}
-
 static struct sh_blockstack *clear_block(struct sh_blockstack *blk)
 {
   memset(blk, 0, sizeof(*blk));
@@ -1082,9 +1299,6 @@
   TT.ff->ifs = TT.ff->next->ifs;
 }
 
-// functions contain pipelines contain functions: prototype because loop
-static void free_pipeline(void *pipeline);
-
 static void free_function(struct sh_function *funky)
 {
   if (--funky->refcount) return;
@@ -1206,29 +1420,6 @@
   return pipes[out];
 }
 
-// utf8 strchr: return wide char matched at wc from chrs, or 0 if not matched
-// if len, save length of next wc (whether or not it's in list)
-static int utf8chr(char *wc, char *chrs, int *len)
-{
-  unsigned wc1, wc2;
-  int ll;
-
-  if (len) *len = 1;
-  if (!*wc) return 0;
-  if (0<(ll = utf8towc(&wc1, wc, 99))) {
-    if (len) *len = ll;
-    while (*chrs) {
-      if(1>(ll = utf8towc(&wc2, chrs, 99))) chrs++;
-      else {
-        if (wc1 == wc2) return wc1;
-        chrs += ll;
-      }
-    }
-  }
-
-  return 0;
-}
-
 // grab variable or special param (ala $$) up to len bytes. Return value.
 // set *used to length consumed. Does not handle $* and $@
 char *getvar_special(char *str, int len, int *used, struct arg_list **delete)
@@ -1384,7 +1575,7 @@
       j = 0;
     }
 
-    // Got wildcard? Return if start of name if out of count, else skip [] ()
+    // Got wildcard? Return start of name if out of count, else skip [] ()
     if (*idx<deck->c && p-pattern == (long)deck->v[*idx]) {
       if (!j++ && !count--) return old;
       ++*idx;
@@ -1589,9 +1780,10 @@
 #define SEMI_IFS (1<<6)    // Use ' ' instead of IFS to combine $*
 // expand str appending to arg using above flag defines, add mallocs to delete
 // if ant not null, save wildcard deck there instead of expanding vs filesystem
-// returns 0 for success, 1 for error
+// returns 0 for success, 1 for error.
+// If measure stop at *measure and return input bytes consumed in *measure
 static int expand_arg_nobrace(struct sh_arg *arg, char *str, unsigned flags,
-  struct arg_list **delete, struct sh_arg *ant)
+  struct arg_list **delete, struct sh_arg *ant, long *measure)
 {
   char cc, qq = flags&NO_QUOTE, sep[6], *new = str, *s, *ss = ss, *ifs, *slice;
   int ii = 0, oo = 0, xx, yy, dd, jj, kk, ll, mm;
@@ -1628,6 +1820,8 @@
     struct sh_arg aa = {0};
     int nosplit = 0;
 
+    if (measure && cc==*measure) break;
+
     // skip literal chars
     if (!strchr("'\"\\$`"+2*(flags&NO_QUOTE), cc)) {
       if (str != new) new[oo] = cc;
@@ -1644,10 +1838,7 @@
     ifs = slice = 0;
 
     // handle escapes and quoting
-    if (cc == '\\') {
-      if (!(qq&1) || (str[ii] && strchr("\"\\$`", str[ii])))
-        new[oo++] = str[ii] ? str[ii++] : cc;
-    } else if (cc == '"') qq++;
+    if (cc == '"') qq++;
     else if (cc == '\'') {
       if (qq&1) new[oo++] = cc;
       else {
@@ -1657,25 +1848,25 @@
 
     // both types of subshell work the same, so do $( here not in '$' below
 // TODO $((echo hello) | cat) ala $(( becomes $( ( retroactively
-    } else if (cc == '`' || (cc == '$' && str[ii] && strchr("([", str[ii]))) {
+    } else if (cc == '`' || (cc == '$' && (str[ii]=='(' || str[ii]=='['))) {
       off_t pp = 0;
 
       s = str+ii-1;
       kk = parse_word(s, 1, 0)-s;
-      if (str[ii] == '[' || *toybuf == 255) {
+      if (str[ii] == '[' || *toybuf == 255) { // (( parsed together, not (( ) )
         struct sh_arg aa = {0};
         long long ll;
 
         // Expand $VARS in math string
         ss = str+ii+1+(str[ii]=='(');
         push_arg(delete, ss = xstrndup(ss, kk - (3+2*(str[ii]!='['))));
-        expand_arg_nobrace(&aa, ss, NO_PATH|NO_SPLIT, delete, 0);
+        expand_arg_nobrace(&aa, ss, NO_PATH|NO_SPLIT, delete, 0, 0);
         s = ss = (aa.v && *aa.v) ? *aa.v : "";
         free(aa.v);
 
         // Recursively calculate result
         if (!recalculate(&ll, &s, 0) || *s) {
-          error_msg("bad math: %s @ %ld", ss, (s-ss)+1);
+          error_msg("bad math: %s @ %ld", ss, (long)(s-ss)+1);
           goto fail;
         }
         ii += kk-1;
@@ -1705,15 +1896,18 @@
 
 // TODO what does \ in `` mean? What is echo `printf %s \$x` supposed to do?
         // This has to be async so pipe buffer doesn't fill up
-        if (!ss) jj = pipe_subshell(s, kk, 0);
+        if (!ss) jj = pipe_subshell(s, kk, 0); // TODO $(true &&) syntax_err()
         if ((ifs = readfd(jj, 0, &pp)))
           for (kk = strlen(ifs); kk && ifs[kk-1]=='\n'; ifs[--kk] = 0);
         close(jj);
       }
+    } else if (cc=='\\' || !str[ii]) {
+      if (!(qq&1) || (str[ii] && strchr("\"\\$`", str[ii])))
+        new[oo++] = str[ii] ? str[ii++] : cc;
 
     // $VARIABLE expansions
 
-    } else if (cc == '$') {
+    } else if (cc == '$' && str[ii]) {
       cc = *(ss = str+ii++);
       if (cc=='\'') {
         for (s = str+ii; *s != '\''; oo += wcrtomb(new+oo, unescape2(&s, 0),0));
@@ -1766,7 +1960,7 @@
           } else {
             // First expansion
             if (strchr("@*", *ss)) { // special case ${!*}/${!@}
-              expand_arg_nobrace(&aa, "\"$*\"", NO_PATH|NO_SPLIT, delete, 0);
+              expand_arg_nobrace(&aa, "\"$*\"", NO_PATH|NO_SPLIT, delete, 0, 0);
               ifs = *aa.v;
               free(aa.v);
               memset(&aa, 0, sizeof(aa));
@@ -1863,7 +2057,7 @@
           }
           if (!lc || *ss != '}') {
             for (s = ss; *s != '}' && *s != ':'; s++);
-            error_msg("bad %.*s @ %ld", (int)(s-slice), slice, ss-slice);
+            error_msg("bad %.*s @ %ld", (int)(s-slice), slice,(long)(ss-slice));
 //TODO fix error message
             goto fail;
           }
@@ -1932,7 +2126,7 @@
             }
 
             if (yy != -1) {
-              if (*delete && (*delete)->arg==ifs) ifs[yy] = 0;
+              if (delete && *delete && (*delete)->arg==ifs) ifs[yy] = 0;
               else push_arg(delete, ifs = xstrndup(ifs, yy));
             }
           }
@@ -1959,7 +2153,7 @@
                 ll++;
                 continue;
               }
-              if (*delete && (*delete)->arg==ifs) {
+              if (delete && *delete && (*delete)->arg==ifs) {
                 if (jj==dd) memcpy(ifs+ll, ss, jj);
                 else if (jj<dd) sprintf(ifs+ll, "%s%s", ss, ifs+ll+dd);
                 else bird = ifs;
@@ -2067,6 +2261,7 @@
   if (str != new) free(new);
   free(deck.v);
   if (ant!=&deck && ant->v) collect_wildcards("", 0, ant);
+  if (measure) *measure = --ii;
 
   return !!arg;
 }
@@ -2093,50 +2288,60 @@
   if ((TT.options&OPT_B) && !(flags&NO_BRACE)) for (i = 0; ; i++) {
     // skip quoted/escaped text
     while ((s = parse_word(old+i, 1, 0)) != old+i) i += s-(old+i);
-    // stop at end of string if we haven't got any more open braces
-    if (!bb && !old[i]) break;
-    // end a brace?
-    if (bb && (!old[i] || old[i] == '}')) {
-      bb->active = bb->commas[bb->cnt+1] = i;
-      // pop brace from bb into bnext
-      for (bnext = bb; bb && bb->active; bb = (bb==blist) ? 0 : bb->prev);
-      // Is this a .. span?
-      j = 1+*bnext->commas;
-      if (old[i] && !bnext->cnt && i-j>=4) {
-        // a..z span? Single digit numbers handled here too. TODO: utf8
-        if (old[j+1]=='.' && old[j+2]=='.') {
-          bnext->commas[2] = old[j];
-          bnext->commas[3] = old[j+3];
-          k = 0;
-          if (old[j+4]=='}' ||
-            (sscanf(old+j+4, "..%u}%n", bnext->commas+4, &k) && k))
-              bnext->cnt = -1;
-        }
-        // 3..11 numeric span?
-        if (!bnext->cnt) {
-          for (k=0, j = 1+*bnext->commas; k<3; k++, j += x)
-            if (!sscanf(old+j, "..%u%n"+2*!k, bnext->commas+2+k, &x)) break;
-          if (old[j] == '}') bnext->cnt = -2;
-        }
-        // Increment goes in the right direction by at least 1
-        if (bnext->cnt) {
-          if (!bnext->commas[4]) bnext->commas[4] = 1;
-          if ((bnext->commas[3]-bnext->commas[2]>0) != (bnext->commas[4]>0))
-            bnext->commas[4] *= -1;
-        }
-      }
-      // discard unterminated span, or commaless span that wasn't x..y
-      if (!old[i] || !bnext->cnt)
-        free(dlist_pop((blist == bnext) ? &blist : &bnext));
-    // starting brace
-    } else if (old[i] == '{') {
+
+    // start a new span
+    if (old[i] == '{') {
       dlist_add_nomalloc((void *)&blist,
         (void *)(bb = xzalloc(sizeof(struct sh_brace)+34*4)));
       bb->commas[0] = i;
+    // end of string: abort unfinished spans and end loop
+    } else if (!old[i]) {
+      for (bb = blist; bb;) {
+        if (!bb->active) {
+          if (bb==blist) {
+            dlist_pop(&blist);
+            bb = blist;
+          } else dlist_pop(&bb);
+        } else bb = (bb->next==blist) ? 0 : bb->next;
+      }
+      break;
     // no active span?
     } else if (!bb) continue;
+    // end current span
+    else if (old[i] == '}') {
+      bb->active = bb->commas[bb->cnt+1] = i;
+      // Is this a .. span?
+      j = 1+*bb->commas;
+      if (!bb->cnt && i-j>=4) {
+        // a..z span? Single digit numbers handled here too. TODO: utf8
+        if (old[j+1]=='.' && old[j+2]=='.') {
+          bb->commas[2] = old[j];
+          bb->commas[3] = old[j+3];
+          k = 0;
+          if (old[j+4]=='}' ||
+            (sscanf(old+j+4, "..%u}%n", bb->commas+4, &k) && k))
+              bb->cnt = -1;
+        }
+        // 3..11 numeric span?
+        if (!bb->cnt) {
+          for (k=0, j = 1+*bb->commas; k<3; k++, j += x)
+            if (!sscanf(old+j, "..%u%n"+2*!k, bb->commas+2+k, &x)) break;
+          if (old[j]=='}') bb->cnt = -2;
+        }
+        // Increment goes in the right direction by at least 1
+        if (bb->cnt) {
+          if (!bb->commas[4]) bb->commas[4] = 1;
+          if ((bb->commas[3]-bb->commas[2]>0) != (bb->commas[4]>0))
+            bb->commas[4] *= -1;
+        }
+      }
+      // discard commaless span that wasn't x..y
+      if (!bb->cnt) free(dlist_pop((blist==bb) ? &blist : &bb));
+      // Set bb to last unfinished brace (if any)
+      for (bb = blist ? blist->prev : 0; bb && bb->active;
+           bb = (bb==blist) ? 0 : bb->prev);
     // add a comma to current span
-    else if (bb && old[i] == ',') {
+    } else if (old[i] == ',') {
       if (bb->cnt && !(bb->cnt&31)) {
         dlist_lpop(&blist);
         dlist_add_nomalloc((void *)&blist,
@@ -2148,7 +2353,7 @@
 
 // TODO NO_SPLIT with braces? (Collate with spaces?)
   // If none, pass on verbatim
-  if (!blist) return expand_arg_nobrace(arg, old, flags, delete, 0);
+  if (!blist) return expand_arg_nobrace(arg, old, flags, delete, 0, 0);
 
   // enclose entire range in top level brace.
   (bstk = xzalloc(sizeof(struct sh_brace)+8))->commas[1] = strlen(old)+1;
@@ -2227,7 +2432,7 @@
     }
 
     // Save result, aborting on expand error
-    if (expand_arg_nobrace(arg, push_arg(delete, ss), flags, delete, 0)) {
+    if (expand_arg_nobrace(arg, push_arg(delete, ss), flags, delete, 0, 0)) {
       llist_traverse(blist, free);
 
       return 1;
@@ -2258,6 +2463,7 @@
   struct sh_arg arg = {0};
   char *s = 0;
 
+  // TODO: ${var:?error} here?
   if (!expand_arg(&arg, new, flags|NO_PATH|NO_SPLIT, del))
     if (!(s = *arg.v) && (flags&(SEMI_IFS|NO_NULL))) s = "";
   free(arg.v);
@@ -2280,7 +2486,7 @@
   pp->urd = urd;
   pp->raw = arg;
 
-  // When we redirect, we copy each displaced filehandle to restore it later.
+  // When redirecting, copy each displaced filehandle to restore it later.
 
   // Expand arguments and perform redirections
   for (j = skip; j<arg->c; j++) {
@@ -2312,7 +2518,7 @@
     }
 
     // Is this a redirect? s = prefix, ss = operator
-    ss = s + redir_prefix(arg->v[j]);
+    ss = skip_redir_prefix(s);
     sss = ss + anystart(ss, (void *)redirectors);
     if (ss == sss) {
       // Nope: save/expand argument and loop
@@ -2332,8 +2538,8 @@
     // It's a redirect: for [to]<from s = start of [to], ss = <, sss = from
     if (isdigit(*s) && ss-s>5) break;
 
-    // expand arguments for everything but << and <<-
-    if (strncmp(ss, "<<", 2) && ss[2] != '<') {
+    // expand arguments for everything but HERE docs
+    if (strncmp(ss, "<<", 2)) {
       struct sh_arg tmp = {0};
 
       if (!expand_arg(&tmp, sss, 0, &pp->delete) && tmp.c == 1) sss = *tmp.v;
@@ -2367,17 +2573,14 @@
     }
 
     // HERE documents?
-    if (!strcmp(ss, "<<<") || !strcmp(ss, "<<-") || !strcmp(ss, "<<")) {
-      char *tmp = getvar("TMPDIR");
+    if (!strncmp(ss, "<<", 2)) {
+      char *tmp = xmprintf("%s/sh-XXXXXX", getvar("TMPDIR") ? : "/tmp");
       int i, len, zap = (ss[2] == '-'), x = !ss[strcspn(ss, "\"'")];
 
-      // store contents in open-but-deleted /tmp file.
-      tmp = xmprintf("%s/sh-XXXXXX", tmp ? tmp : "/tmp");
+      // store contents in open-but-deleted /tmp file: write then lseek(start)
       if ((from = mkstemp(tmp))>=0) {
         if (unlink(tmp)) bad++;
-
-        // write contents to file (if <<< else <<) then lseek back to start
-        else if (ss[2] == '<') {
+        else if (ss[2] == '<') { // not stored in arg[here]
           if (!(ss = expand_one_arg(sss, 0, 0))) {
             s = 0;
             break;
@@ -2386,21 +2589,21 @@
           if (len != writeall(from, ss, len)) bad++;
           if (ss != sss) free(ss);
         } else {
-          struct sh_arg *hh = arg+here++;
+          struct sh_arg *hh = arg+ ++here;
 
           for (i = 0; i<hh->c; i++) {
             ss = hh->v[i];
             sss = 0;
 // TODO audit this ala man page
             // expand_parameter, commands, and arithmetic
-            if (x && !(ss = sss = expand_one_arg(ss, ~SEMI_IFS, 0))) {
+            if (x && !(sss = expand_one_arg(ss, ~SEMI_IFS, 0))) {
               s = 0;
               break;
             }
 
             while (zap && *ss == '\t') ss++;
             x = writeall(from, ss, len = strlen(ss));
-            free(sss);
+            if (ss != sss) free(sss);
             if (len != x) break;
           }
           if (i != hh->c) bad++;
@@ -2541,19 +2744,43 @@
 {
   char *s, *ss, *sss;
   struct sh_arg *arg = TT.ff->pl->arg;
-  int envlen, funk = TT.funcslen, jj = 0, prefix = 0;
+  int envlen, skiplen, funk = TT.funcslen, ii, jj = 0, prefix = 0;
   struct sh_process *pp;
 
   // Count leading variable assignments
-  for (envlen = 0; envlen<arg->c; envlen++)
+  for (envlen = skiplen = 0; envlen<arg->c; envlen++)
     if ((ss = varend(arg->v[envlen]))==arg->v[envlen] || ss[*ss=='+']!='=')
       break;
-  pp = expand_redir(arg, envlen, 0);
+
+  // Skip [[ ]] and (( )) contents for now
+  if ((s = arg->v[envlen])) {
+    if (!smemcmp(s, "((", 2)) skiplen = 1;
+    else if (!strcmp(s, "[[")) while (strcmp(arg->v[envlen+skiplen++], "]]"));
+  }
+  pp = expand_redir(arg, envlen+skiplen, 0);
+
+// TODO: if error stops redir, expansion assignments, prefix assignments,
+// what sequence do they occur in?
+  if (skiplen) {
+    // Trailing redirects can't expand to any contents
+    if (pp->arg.c) {
+      syntax_err(*pp->arg.v);
+      pp->exit = 1;
+    }
+    if (!pp->exit) {
+      for (ii = 0; ii<skiplen; ii++)
+// TODO: [[ ~ ] expands but ((~)) doesn't, what else?
+        if (expand_arg(&pp->arg, arg->v[envlen+ii], NO_PATH|NO_SPLIT, &pp->delete))
+          break;
+      if (ii != skiplen) pp->exit = toys.exitval = 1;
+    }
+    if (pp->exit) return pp;
+  }
 
   // Are we calling a shell function?  TODO binary search
-  if (pp->arg.c && !strchr(*pp->arg.v, '/'))
-    for (funk = 0; funk<TT.funcslen; funk++)
-       if (!strcmp(*pp->arg.v, TT.functions[funk]->name)) break;
+  if (pp->arg.c)
+    if (!strchr(s, '/')) for (funk = 0; funk<TT.funcslen; funk++)
+       if (!strcmp(s, TT.functions[funk]->name)) break;
 
   // Create new function context to hold local vars?
   if (funk != TT.funcslen || (envlen && pp->arg.c) || TT.ff->blk->pipe) {
@@ -2590,8 +2817,21 @@
 // TODO what about "echo | x=1 | export fruit", must subshell? Test this.
 //   Several NOFORK can just NOP in a pipeline? Except ${a?b} still errors
 
+  // ((math))
+  else if (!smemcmp(s = *pp->arg.v, "((", 2)) {
+    char *ss = s+2;
+    long long ll;
+
+    funk = TT.funcslen;
+    ii = strlen(s)-2;
+    if (!recalculate(&ll, &ss, 0) || ss!=s+ii)
+      perror_msg("bad math: %.*s @ %ld", ii-2, s+2, (long)(ss-s)-2);
+    else toys.exitval = !ll;
+    pp->exit = toys.exitval;
+    s = 0; // Really!
+
   // call shell function
-  else if (funk != TT.funcslen) {
+  } else if (funk != TT.funcslen) {
     s = 0; // $_ set on return, not here
     (TT.ff->func = TT.functions[funk])->refcount++;
     TT.ff->pl = TT.ff->func->pipeline;
@@ -2605,7 +2845,6 @@
     s = pp->arg.v[pp->arg.c-1];
     sss = pp->arg.v[pp->arg.c];
 //dprintf(2, "%d run command %p %s\n", getpid(), TT.ff, *pp->arg.v); debug_show_fds();
-// TODO handle ((math)): else if (!strcmp(*pp->arg.v, "(("))
 // TODO: figure out when can exec instead of forking, ala sh -c blah
 
     // Is this command a builtin that should run in this process?
@@ -2630,6 +2869,7 @@
       }
       toys.rebound = 0;
       pp->exit = toys.exitval;
+      clearerr(stdout);
       if (toys.optargs != toys.argv+1) free(toys.optargs);
       if (toys.old_umask) umask(toys.old_umask);
       memcpy(&toys, &temp, jj);
@@ -2716,22 +2956,28 @@
 
     // is a HERE document in progress?
     } else if (pl->count != pl->here) {
-      arg += 1+pl->here;
+      // Back up to oldest unfinished pipeline segment.
+      while (pl != *ppl && pl->prev->count != pl->prev->here) pl = pl->prev;
+      arg = pl->arg+1+pl->here;
 
       // Match unquoted EOF.
-      for (s = line, end = arg->v[arg->c]; *s && *end; s++) {
+      for (s = line, end = arg->v[arg->c]; *end; s++, end++) {
         s += strspn(s, "\\\"'");
-        if (*s != *end) break;
+        if (!*s || *s != *end) break;
       }
       // Add this line, else EOF hit so end HERE document
-      if (!*s && !*end) {
+      if (*s || *end) {
         end = arg->v[arg->c];
         arg_add(arg, xstrdup(line));
         arg->v[arg->c] = end;
       } else {
+        // End segment and advance/consume bridge segments
         arg->v[arg->c] = 0;
-        pl->here++;
+        if (pl->count == ++pl->here)
+          while (pl->next != *ppl && (pl = pl->next)->here == -1)
+            pl->here = pl->count;
       }
+      if (pl->here != pl->count) return 1;
       start = 0;
 
     // Nope, new segment if not self-managing type
@@ -2744,63 +2990,30 @@
 
     // Look for << HERE redirections in completed pipeline segment
     if (pl && pl->count == -1) {
-      pl->count = 0;
-      arg = pl->arg;
-
       // find arguments of the form [{n}]<<[-] with another one after it
-      for (i = 0; i<arg->c; i++) {
-        s = arg->v[i] + redir_prefix(arg->v[i]);
-// TODO <<< is funky
-// argc[] entries removed from main list? Can have more than one?
-        if (strcmp(s, "<<") && strcmp(s, "<<-") && strcmp(s, "<<<")) continue;
+      for (arg = pl->arg, pl->count = i = 0; i<arg->c; i++) {
+        s = skip_redir_prefix(arg->v[i]);
+        if (strncmp(s, "<<", 2) || s[2]=='<') continue;
         if (i+1 == arg->c) goto flush;
 
-        // Add another arg[] to the pipeline segment (removing/readding to list
-        // because realloc can move pointer)
+        // Add another arg[] to the pipeline segment (removing/re-adding
+        // to list because realloc can move pointer, and adjusing end pointers)
         dlist_lpop(ppl);
-        pl = xrealloc(pl, sizeof(*pl) + ++pl->count*sizeof(struct sh_arg));
+        pl2 = pl;
+        pl = xrealloc(pl, sizeof(*pl)+(++pl->count+1)*sizeof(struct sh_arg));
+        arg = pl->arg;
         dlist_add_nomalloc((void *)ppl, (void *)pl);
-
-        // queue up HERE EOF so input loop asks for more lines.
-        arg[pl->count].v = xzalloc(2*sizeof(void *));
-        arg[pl->count].v[0] = arg->v[++i];
-        arg[pl->count].v[1] = 0;
-        arg[pl->count].c = 0;
-        if (s[2] == '<') pl->here++; // <<< doesn't load more data
-      }
-
-      // Did we just end a function?
-      if (ex == (void *)1) {
-        struct sh_function *funky;
-
-        // function must be followed by a compound statement for some reason
-        if ((*ppl)->prev->type != 3) {
-          s = *(*ppl)->prev->arg->v;
-          goto flush;
+        for (pl3 = *ppl;;) {
+          if (pl3->end == pl2) pl3->end = pl;
+          if ((pl3 = pl3->next) == *ppl) break;
         }
 
-        // Back up to saved function() statement and create sh_function
-        free(dlist_lpop(expect));
-        pl = (void *)(*expect)->data;
-        funky = xmalloc(sizeof(struct sh_function));
-        funky->refcount = 1;
-        funky->name = *pl->arg->v;
-        *pl->arg->v = (void *)funky;
-
-        // Chop out pipeline segments added since saved function
-        funky->pipeline = pl->next;
-        pl->next->prev = (*ppl)->prev;
-        (*ppl)->prev->next = pl->next;
-        pl->next = *ppl;
-        (*ppl)->prev = pl;
-        dlist_terminate(funky->pipeline = add_pl(&funky->pipeline, 0));
-        funky->pipeline->type = 'f';
-
-        // Immature function has matured (meaning cleanup is different)
-        pl->type = 'F';
-        free(dlist_lpop(expect));
-        ex = *expect ? (*expect)->prev->data : 0;
+        // queue up HERE EOF so input loop asks for more lines.
+        *(arg[pl->count].v = xzalloc(2*sizeof(void *))) = arg->v[++i];
+        arg[pl->count].c = 0;
       }
+      // Mark "bridge" segment when previous pl had HERE but this doesn't
+      if (!pl->count && pl->prev->count != pl->prev->here) pl->prev->here = -1;
       pl = 0;
     }
     if (done) break;
@@ -2812,15 +3025,13 @@
 
     // Parse next word and detect overflow (too many nested quotes).
     if ((end = parse_word(start, 0, 0)) == (void *)1) goto flush;
-//dprintf(2, "%d %p %s word=%.*s\n", getpid(), pl, (ex != (void *)1) ? ex : "function", (int)(end-start), end ? start : "");
+//dprintf(2, "%d %p(%d) %s word=%.*s\n", getpid(), pl, pl ? pl->type : -1, ex, (int)(end-start), end ? start : "");
 
+    // End function declaration?
     if (pl && pl->type == 'f' && arg->c == 1 && (end-start!=1 || *start!='(')) {
-funky:
-      // end function segment, expect function body
-      dlist_add(expect, (void *)pl);
-      pl = 0;
-      dlist_add(expect, (void *)1);
+      // end (possibly multiline) function segment, expect function body next
       dlist_add(expect, 0);
+      pl = 0;
 
       continue;
     }
@@ -2841,7 +3052,7 @@
     // Ok, we have a word. What does it _mean_?
 
     // case/esac parsing is weird (unbalanced parentheses!), handle first
-    i = (unsigned long)ex>1 && !strcmp(ex, "esac") &&
+    i = ex && !strcmp(ex, "esac") &&
         ((pl->type && pl->type != 3) || (*start==';' && end-start>1));
     if (i) {
 
@@ -2854,7 +3065,7 @@
       }
 
       // type 0 means just got ;; so start new type 2
-      if (!pl->type) {
+      if (!pl->type || pl->type==3) {
         // catch "echo | ;;" errors
         if (arg->v && arg->v[arg->c] && strcmp(arg->v[arg->c], "&")) goto flush;
         if (!arg->c) {
@@ -2874,6 +3085,7 @@
     // Did we hit end of line or ) outside a function declaration?
     // ) is only saved at start of a statement, ends current statement
     } else if (end == start || (arg->c && *start == ')' && pl->type!='f')) {
+//TODO: test ) within ]]
       // function () needs both parentheses or neither
       if (pl->type == 'f' && arg->c != 1 && arg->c != 3) {
         s = "function(";
@@ -2881,7 +3093,7 @@
       }
 
       // "for" on its own line is an error.
-      if (arg->c == 1 && (unsigned long)ex>1 && !memcmp(ex, "do\0A", 4)) {
+      if (arg->c == 1 && !smemcmp(ex, "do\0A", 4)) {
         s = "newline";
         goto flush;
       }
@@ -2959,7 +3171,8 @@
       if (arg->c == 2 && strcmp(s, "(")) goto flush;
       if (arg->c == 3) {
         if (strcmp(s, ")")) goto flush;
-        goto funky;
+        dlist_add(expect, 0);
+        pl = 0;
       }
 
       continue;
@@ -2968,26 +3181,25 @@
     } else if (strchr(";|&", *s) && strncmp(s, "&>", 2)) {
       arg->c--;
 
+      // Connecting nonexistent statements is an error
+      if (!arg->c || !smemcmp(ex, "do\0A", 4)) goto flush;
+
       // treat ; as newline so we don't have to check both elsewhere.
       if (!strcmp(s, ";")) {
         arg->v[arg->c] = 0;
         free(s);
         s = 0;
 // TODO can't have ; between "for i" and in or do. (Newline yes, ; no. Why?)
-        if (!arg->c && (unsigned long)ex>1 && !memcmp(ex, "do\0C", 4)) continue;
+        if (!arg->c && !smemcmp(ex, "do\0C", 4)) continue;
 
       // ;; and friends only allowed in case statements
       } else if (*s == ';') goto flush;
-
-      // flow control without a statement is an error
-      if (!arg->c) goto flush;
       pl->count = -1;
 
       continue;
 
     // a for/select must have at least one additional argument on same line
-    } else if ((unsigned long)ex>1 && !memcmp(ex, "do\0A", 4)) {
-
+    } else if (!smemcmp(ex, "do\0A", 4)) {
       // Sanity check and break the segment
       if (strncmp(s, "((", 2) && *varend(s)) goto flush;
       pl->count = -1;
@@ -2996,22 +3208,24 @@
       continue;
 
     // flow control is the first word of a pipeline segment
-    } else if (arg->c>1) continue;
+    } else if (arg->c>1) {
+      // Except that [[ ]] is a type 0 segment
+      if (ex && *ex==']' && !strcmp(s, ex)) free(dlist_lpop(expect));
 
-    // Do we expect something that _must_ come next? (no multiple statements)
-    if ((unsigned long)ex>1) {
-      // The "test" part of for/select loops can have (at most) one "in" line,
-      // for {((;;))|name [in...]} do
-      if (!memcmp(ex, "do\0C", 4)) {
-        if (strcmp(s, "do")) {
-          // can only have one "in" line between for/do, but not with for(())
-          if (pl->prev->type == 's') goto flush;
-          if (!strncmp(pl->prev->arg->v[1], "((", 2)) goto flush;
-          else if (strcmp(s, "in")) goto flush;
-          pl->type = 's';
+      continue;
+    }
 
-          continue;
-        }
+    // The "test" part of for/select loops can have (at most) one "in" line,
+    // for {((;;))|name [in...]} do
+    if (!smemcmp(ex, "do\0C", 4)) {
+      if (strcmp(s, "do")) {
+        // can only have one "in" line between for/do, but not with for(())
+        if (pl->prev->type == 's') goto flush;
+        if (!strncmp(pl->prev->arg->v[1], "((", 2)) goto flush;
+        else if (strcmp(s, "in")) goto flush;
+        pl->type = 's';
+
+        continue;
       }
     }
 
@@ -3030,28 +3244,36 @@
     if (!strcmp(s, "if")) end = "then";
     else if (!strcmp(s, "while") || !strcmp(s, "until")) end = "do\0B";
     else if (!strcmp(s, "{")) end = "}";
-    else if (!strcmp(s, "[[")) end = "]]";
     else if (!strcmp(s, "(")) end = ")";
+    else if (!strcmp(s, "[[")) end = "]]";
 
-    // Expecting NULL means a statement: I.E. any otherwise unrecognized word
-    if (!ex && *expect) free(dlist_lpop(expect));
+    // Expecting NULL means any statement (don't care which).
+    if (!ex && *expect) {
+      if (pl->prev->type == 'f' && !end && smemcmp(s, "((", 2)) goto flush;
+      free(dlist_lpop(expect));
+    }
 
     // Did we start a new statement
     if (end) {
-      pl->type = 1;
+      if (*end!=']') pl->type = 1;
+      else {
+        // [[ ]] is a type 0 segment, not a flow control block
+        dlist_add(expect, end);
+        continue;
+      }
 
       // Only innermost statement needed in { { { echo ;} ;} ;} and such
       if (*expect && !(*expect)->prev->data) free(dlist_lpop(expect));
 
-    // if can't end a statement here skip next few tests
-    } else if ((unsigned long)ex<2);
+    // if not looking for end of statement skip next few tests
+    } else if (!ex);
 
     // If we got here we expect a specific word to end this block: is this it?
     else if (!strcmp(s, ex)) {
       // can't "if | then" or "while && do", only ; & or newline works
       if (strcmp(pl->prev->arg->v[pl->prev->arg->c] ? : "&", "&")) goto flush;
 
-      // consume word, record block end location in earlier !0 type blocks
+      // consume word, record block end in earlier !0 type (non-nested) blocks
       free(dlist_lpop(expect));
       if (3 == (pl->type = anystr(s, tails) ? 3 : 2)) {
         for (i = 0, pl2 = pl3 = pl; (pl2 = pl2->prev);) {
@@ -3060,7 +3282,7 @@
             if (!i) {
               if (pl2->type == 2) {
                 pl2->end = pl3;
-                pl3 = pl2;
+                pl3 = pl2;   // chain multiple gearshifts for case/esac
               } else pl2->end = pl;
             }
             if (pl2->type == 1 && --i<0) break;
@@ -3105,18 +3327,44 @@
 
   // ignore blank and comment lines
   if (!*ppl) return 0;
-
-// TODO <<< has no parsing impact, why play with it here at all?
-  // advance past <<< arguments (stored as here documents, but no new input)
   pl = (*ppl)->prev;
-  while (pl->count<pl->here && pl->arg[pl->count].c<0)
-    pl->arg[pl->count++].c = 0;
 
   // return if HERE document pending or more flow control needed to complete
+  if (pl->count != pl->here) return 1;
   if (*expect) return 1;
-  if (*ppl && pl->count != pl->here) return 1;
   if (pl->arg->v[pl->arg->c] && strcmp(pl->arg->v[pl->arg->c], "&")) return 1;
 
+  // Transplant completed function bodies into reference counted structures
+  for (;;) {
+    if (pl->type=='f') {
+      struct sh_function *funky;
+
+      // Create sh_function struct, attach to declaration's pipeline segment
+      funky = xmalloc(sizeof(struct sh_function));
+      funky->refcount = 1;
+      funky->name = *pl->arg->v;
+      *pl->arg->v = (void *)funky;
+      pl->type = 'F'; // different cleanup
+
+      // Transplant function body into new struct, re-circling both lists
+      pl2 = pl->next;
+      // Add NOP 'f' segment (TODO: remove need for this?)
+      (funky->pipeline = add_pl(&pl2, 0))->type = 'f';
+      // Find end of block
+      for (i = 0, pl3 = pl2->next;;pl3 = pl3->next)
+        if (pl3->type == 1) i++;
+        else if (pl3->type == 3 && --i<0) break;
+      // Chop removed segment out of old list.
+      pl3->next->prev = pl;
+      pl->next = pl3->next;
+      // Terminate removed segment.
+      pl2->prev = 0;
+      pl3->next = 0;
+    }
+    if (pl == *ppl) break;
+    pl = pl->prev;
+  }
+
   // Don't need more input, can start executing.
 
   dlist_terminate(*ppl);
@@ -3310,6 +3558,7 @@
 // TODO: ctrl-z during script read having already read partial line,
 // SIGSTOP and SIGTSTP need SA_RESTART, but child proc should stop
 // TODO if (!isspace(*new)) add_to_history(line);
+// TODO: embedded nul bytes need signaling for the "tried to run binary" test.
 
   for (new = 0, len = 0;;) {
     errno = 0;
@@ -3457,8 +3706,7 @@
           break;
         }
       // Parse and run next command, saving resulting process
-      } else if ((pp = run_command()))
-        dlist_add_nomalloc((void *)&pplist, (void *)pp);
+      } else dlist_add_nomalloc((void *)&pplist, (void *)run_command());
 
     // Start of flow control block?
     } else if (TT.ff->pl->type == 1) {
@@ -3483,7 +3731,7 @@
 // TODO test background a block: { abc; } &
 
       // If we spawn a subshell, pass data off to child process
-      if (TT.ff->blk->pipe || !strcmp(s, "(") || (ctl && !strcmp(ctl, "&"))) {
+      if (TT.ff->blk->next->pipe || !strcmp(s, "(") || (ctl && !strcmp(ctl, "&"))) {
         if (!(pp->pid = run_subshell(0, -1))) {
 
           // zap forked child's cleanup context and advance to next statement
@@ -3509,10 +3757,39 @@
 
         // for/select/do/done: populate blk->farg with expanded args (if any)
         if (!strcmp(s, "for") || !strcmp(s, "select")) {
-          if (TT.ff->blk->loop);
+          if (TT.ff->blk->loop); // skip init, not first time through loop
+
+          // in (;;)
           else if (!strncmp(TT.ff->blk->fvar = ss, "((", 2)) {
+            char *in = ss+2, *out;
+            long long ll;
+
             TT.ff->blk->loop = 1;
-dprintf(2, "TODO skipped init for((;;)), need math parser\n");
+            for (i = 0; i<3; i++) {
+              if (i==2) k = strlen(in)-2;
+              else {
+                // perform expansion but immediately discard it to find ;
+                k = ';';
+                pp = xzalloc(sizeof(*pp));
+                if (expand_arg_nobrace(&pp->arg, ss+2, NO_PATH|NO_SPLIT,
+                    &pp->delete, 0, &k)) break;
+                free_process(pp);
+                if (in[k] != ';') break;
+              }
+              (out = xmalloc(k+1))[k] = 0;
+              memcpy(out, in, k);
+              arg_add(&TT.ff->blk->farg, push_arg(&TT.ff->blk->fdelete, out));
+              in += k+1;
+            }
+            if (i!=3) {
+              syntax_err(ss);
+              break;
+            }
+            in = out = *TT.ff->blk->farg.v;
+            if (!recalculate(&ll, &in, 0) || *in) {
+              perror_msg("bad math: %s @ %ld", in, (long)(in-out));
+              break;
+            }
 
           // in LIST
           } else if (TT.ff->pl->next->type == 's') {
@@ -3563,7 +3840,7 @@
             }
             arg.c = arg2.c = 0;
             if ((err = expand_arg_nobrace(&arg, *vv++, NO_SPLIT,
-              &TT.ff->blk->fdelete, &arg2))) break;
+              &TT.ff->blk->fdelete, &arg2, 0))) break;
             s = arg.c ? *arg.v : "";
             match = wildcard_match(TT.ff->blk->fvar, s, &arg2, 0);
             if (match>=0 && !s[match]) break;
@@ -3606,7 +3883,21 @@
           }
         } else if (blk->loop >= blk->farg.c) TT.ff->pl = pop_block();
         else if (!strncmp(blk->fvar, "((", 2)) {
-dprintf(2, "TODO skipped running for((;;)), need math parser\n");
+          char *aa, *bb;
+          long long ll;
+
+          for (i = 2; i; i--) {
+            if (TT.ff->blk->loop == 1) {
+              TT.ff->blk->loop++;
+              i--;
+            }
+            aa = bb = TT.ff->blk->farg.v[i];
+            if (!recalculate(&ll, &aa, 0) || *aa) {
+              perror_msg("bad math: %s @ %ld", aa, (long)(aa-bb));
+              break;
+            }
+            if (i==1 && !ll) TT.ff->pl = pop_block();
+          }
         } else setvarval(blk->fvar, blk->farg.v[blk->loop++]);
       }
 
@@ -3753,6 +4044,8 @@
     goto end;
   }
 
+  if (name) TT.ff->omnom = name;
+
 // TODO fix/catch NONBLOCK on input?
 // TODO when DO we reset lineno? (!LINENO means \0 returns 1)
 // when do we NOT reset lineno? Inherit but preserve perhaps? newline in $()?
@@ -3764,7 +4057,7 @@
     // did we exec an ELF file or something?
     if (!TT.LINENO++ && name && new) {
       // A shell script's first line has no high bytes that aren't valid utf-8.
-      for (ii = 0; new[ii] && 0<(cc = utf8towc(&wc, new+ii, 4)); ii += cc);
+      for (ii = 0; new[ii]>6 && 0<(cc = utf8towc(&wc, new+ii, 4)); ii += cc);
       if (new[ii]) {
 is_binary:
         if (name) error_msg("'%s' is binary", name); // TODO syntax_err() exit?
@@ -3780,9 +4073,8 @@
     more = parse_line(new ? : " ", &pl, &expect);
     free(new);
     if (more==1) {
-      if (!new) {
-        if (!ff) syntax_err("unexpected end of file");
-      } else continue;
+      if (!new) syntax_err("unexpected end of file");
+      else continue;
     } else if (!more && pl) {
       TT.ff->pl = pl;
       run_lines();
@@ -3832,7 +4124,7 @@
   // Read named variables: type, len, var=value\0
   for (;;) {
     len = ll = 0;
-    fscanf(fp, "%u %lu%*[^\n]", &len, &ll);
+    (void)fscanf(fp, "%u %lu%*[^\n]", &len, &ll);
     fgetc(fp); // Discard the newline fscanf didn't eat.
     if (!len) break;
     (s = xmalloc(len+1))[len] = 0;
@@ -3901,7 +4193,7 @@
       shv->flags |= VAR_EXPORT;
       shv->str = s;
     }
-    cache_ifs(s, TT.ff);
+    cache_ifs(s, TT.ff); // TODO: replace with set(get("IFS")) after loop
   }
 
   // set/update PWD
@@ -4394,7 +4686,10 @@
   call_function();
   TT.ff->arg.v = toys.optargs;
   TT.ff->arg.c = toys.optc;
+  TT.ff->oldlineno = TT.LINENO;
+  TT.LINENO = 0;
   do_source(name, ff);
+  TT.LINENO = TT.ff->oldlineno;
   free(dlist_pop(&TT.ff));
   --TT.srclvl;
 }
diff --git a/toys/pending/strace.c b/toys/pending/strace.c
index ae8fca9..e340a4f 100644
--- a/toys/pending/strace.c
+++ b/toys/pending/strace.c
@@ -33,9 +33,6 @@
   int arg;
 )
 
-  struct user_regs_struct regs;
-
-
 // Syscall args from https://man7.org/linux/man-pages/man2/syscall.2.html
 // REG_ORDER is args 0-6, SYSCALL, RESULT
 #if defined(__ARM_EABI__)
@@ -50,6 +47,9 @@
 static const char REG_ORDER[] = {0,1,2,3,4,7,16,14};
 #elif defined(__PPC__) || defined(__PPC64__)
 static const char REG_ORDER[] = {3,4,5,6,7,8,0,3};
+#elif defined(__riscv)
+// a0,a1,a2,a3,a4,a5,a7,a0
+static const char REG_ORDER[] = {10,11,12,13,14,15,17,10};
 #elif defined(__s390__) // also covers s390x
 // r2,r3,r4,r5,r6,r7,r1,r2 but mask+addr before r0 so +2
 static const char REG_ORDER[] = {4,5,6,7,8,9,3,4};
@@ -164,12 +164,14 @@
 
 static void xptrace(int req, pid_t pid, void *addr, void *data)
 {
-  if (ptrace(req, pid, addr, data)) perror_exit("ptrace pid %d", pid);
+  if (ptrace(req, pid, addr, data)) perror_exit("ptrace %d pid %d", req, pid);
 }
 
-static void get_regs()
+static void get_regs(void)
 {
-  xptrace(PTRACE_GETREGS, TT.pid, 0, TT.regs);
+  struct iovec v = {.iov_base=&TT.regs, .iov_len=sizeof(TT.regs)};
+
+  xptrace(PTRACE_GETREGSET, TT.pid, (void *)1, &v); // NT_PRSTATUS
 }
 
 static void ptrace_struct(long addr, void *dst, size_t bytes)
@@ -242,11 +244,12 @@
     if (FLAG(v)) {
       // TODO: full atime/mtime/ctime dump.
       fprintf(stderr, "{st_dev=makedev(%#x, %#x), st_ino=%ld, st_mode=%o, "
-          "st_nlink=%ld, st_uid=%d, st_gid=%d, st_blksize=%ld, st_blocks=%ld, "
-          "st_size=%lld, st_atime=%ld, st_mtime=%ld, st_ctime=%ld}",
-          dev_major(sb.st_dev), dev_minor(sb.st_dev), sb.st_ino, sb.st_mode,
-          sb.st_nlink, sb.st_uid, sb.st_gid, sb.st_blksize, sb.st_blocks,
-          (long long)sb.st_size, sb.st_atime, sb.st_mtime, sb.st_ctime);
+        "st_nlink=%ld, st_uid=%d, st_gid=%d, st_blksize=%ld, st_blocks=%ld, "
+        "st_size=%lld, st_atime=%ld, st_mtime=%ld, st_ctime=%ld}",
+        dev_major(sb.st_dev), dev_minor(sb.st_dev), sb.st_ino, sb.st_mode,
+        (long) sb.st_nlink, sb.st_uid, sb.st_gid, (long) sb.st_blksize,
+        sb.st_blocks, (long long)sb.st_size, sb.st_atime, sb.st_mtime,
+        sb.st_ctime);
     } else {
       fprintf(stderr, "{st_mode=%o, st_size=%lld, ...}", sb.st_mode,
         (long long)sb.st_size);
@@ -356,7 +359,10 @@
   if (strstart(&TT.fmt, "access|")) {
     print_bitmask(1, v, "F_OK", C(R_OK), C(W_OK), C(X_OK), 0);
   } else if (strstart(&TT.fmt, "mmap|")) {
-    print_bitmask(1, v, 0, C(MAP_SHARED), C(MAP_PRIVATE), C(MAP_32BIT),
+    print_bitmask(1, v, 0, C(MAP_SHARED), C(MAP_PRIVATE),
+#if defined(MAP_32BIT)
+        C(MAP_32BIT),
+#endif
         C(MAP_ANONYMOUS), C(MAP_FIXED), C(MAP_GROWSDOWN), C(MAP_HUGETLB),
         C(MAP_DENYWRITE), 0);
   } else if (strstart(&TT.fmt, "open|")) {
@@ -367,6 +373,8 @@
         0x4000, "O_DIRECT", 0x8000, "O_LARGEFILE", 0x410000, "O_TMPFILE", 0);
   } else if (strstart(&TT.fmt, "prot|")) {
     print_bitmask(1,v,"PROT_NONE",C(PROT_READ),C(PROT_WRITE),C(PROT_EXEC),0);
+  } else if (strstart(&TT.fmt, "grnd|")) {
+    print_bitmask(1,v,"0",C(GRND_RANDOM),C(GRND_NONBLOCK),0);
   } else abort();
 }
 
@@ -411,7 +419,7 @@
                 if (!(s = num_to_sig(v))) fprintf(stderr, "%ld", v);
                 else fprintf(stderr, "SIG%s", s);
                 break;
-      case 'z': fprintf(stderr, "%zd", v); break; // size_t
+      case 'z': fprintf(stderr, "%ld", (long) v); break; // size_t
       case 'x': fprintf(stderr, "%lx", v); break; // hex
 
       case '{': print_struct(v); break;
@@ -469,21 +477,29 @@
     }
   } else switch (TT.syscall) {
 #define SC(n,f) case __NR_ ## n: name = #n; TT.fmt = f; break
+#if defined(__NR_access)
     SC(access, "s|access|");
+#endif
+#if defined(__NR_arch_prctl)
     SC(arch_prctl, "dp");
+#endif
     SC(brk, "p");
     SC(close, "d");
     SC(connect, "fpd"); // TODO: sockaddr
     SC(dup, "f");
+#if defined(__NR_dup2)
     SC(dup2, "ff");
+#endif
     SC(dup3, "ff|open|");
     SC(execve, "spp");
     SC(exit_group, "d");
+    SC(faccessat, "fs|access|");
     SC(fcntl, "fdp"); // TODO: probably needs special case
     SC(fstat, "f/{stat}");
     SC(futex, "pdxppx");
     SC(getdents64, "dpz");
     SC(geteuid, "");
+    SC(getrandom, "pz|grnd|");
     SC(getuid, "");
 
     SC(getxattr, "sspz");
@@ -491,16 +507,24 @@
     SC(fgetxattr, "fspz");
 
     SC(lseek, "fo^seek^");
+#if defined(__NR_lstat)
     SC(lstat, "s/{stat}");
+#endif
     SC(mmap, "pz|prot||mmap|fx");
     SC(mprotect, "pz|prot|");
     SC(mremap, "pzzdp"); // TODO: flags
     SC(munmap, "pz");
     SC(nanosleep, "{timespec}/{timespec}");
+#if defined(__NR_newfstatat)
     SC(newfstatat, "fs/{stat}d");
+#endif
+#if defined(__NR_open)
     SC(open, "sd|open|m");
+#endif
     SC(openat, "fs|open|m");
+#if defined(__NR_poll)
     SC(poll, "pdd");
+#endif
     SC(prlimit64, "d^rlimit^{rlimit}/{rlimit}");
     SC(read, "d/sz");
     SC(readlinkat, "s/sz");
@@ -509,7 +533,9 @@
     SC(set_robust_list, "pd");
     SC(set_tid_address, "p");
     SC(socket, "ddd"); // TODO: flags
+#if defined(__NR_stat)
     SC(stat, "s/{stat}");
+#endif
     SC(statfs, "sp");
     SC(sysinfo, "p");
     SC(umask, "m");
diff --git a/toys/pending/sulogin.c b/toys/pending/sulogin.c
index c773e63..f58754b 100644
--- a/toys/pending/sulogin.c
+++ b/toys/pending/sulogin.c
@@ -13,7 +13,6 @@
 config SULOGIN
   bool "sulogin"
   default n
-  depends on TOYBOX_SHADOW
   help
     usage: sulogin [-t time] [tty]
 
diff --git a/toys/pending/tcpsvd.c b/toys/pending/tcpsvd.c
index e5bd76b..fb0aa77 100644
--- a/toys/pending/tcpsvd.c
+++ b/toys/pending/tcpsvd.c
@@ -6,7 +6,7 @@
  * 
  * No Standard.
 
-USE_TCPSVD(NEWTOY(tcpsvd, "^<3c#=30<1C:b#=20<0u:l:hEv", TOYFLAG_USR|TOYFLAG_BIN))
+USE_TCPSVD(NEWTOY(tcpsvd, "^<3c#=30<1b#=20<0C:u:l:hEv", TOYFLAG_USR|TOYFLAG_BIN))
 USE_TCPSVD(OLDTOY(udpsvd, tcpsvd, TOYFLAG_USR|TOYFLAG_BIN))
 
 config TCPSVD
@@ -39,11 +39,8 @@
 #include "toys.h"
 
 GLOBALS(
-  char *name;
-  char *user;
-  long bn;
-  char *nmsg;
-  long cn;
+  char *l, *u, *C;
+  long b, c;
 
   int maxc;
   int count_all;
@@ -101,7 +98,7 @@
 }
 
 // Hashing of IP address.
-static int haship( char *addr)
+static int haship(char *addr)
 {
   uint32_t ip[8] = {0,};
   int count = 0, i = 0;
@@ -171,18 +168,17 @@
 {
   int status;
   pid_t pid_n = wait(&status);
+  char *ip = (pid_n<1) ? 0 : delete(&pids, pid_n);
 
-  if (pid_n <= 0) return;
-  char *ip = delete(&pids, pid_n);
   if (!ip) return;
   remove_connection(ip);
   TT.count_all--;
-  if (toys.optflags & FLAG_v) {
+  if (FLAG(v)) {
     if (WIFEXITED(status))
       xprintf("%s: end %d exit %d\n",toys.which->name, pid_n, WEXITSTATUS(status));
     else if (WIFSIGNALED(status))
       xprintf("%s: end %d signaled %d\n",toys.which->name, pid_n, WTERMSIG(status));
-    if (TT.cn > 1) xprintf("%s: status %d/%d\n",toys.which->name, TT.count_all, TT.cn);
+    if (TT.c > 1) xprintf("%s: status %d/%ld\n",toys.which->name, TT.count_all, TT.c);
   }
 }
 
@@ -236,7 +232,7 @@
 
   memset(&hints, 0, sizeof hints);
   hints.ai_family = AF_UNSPEC;  
-  hints.ai_socktype = ((TT.udp) ?SOCK_DGRAM : SOCK_STREAM);
+  hints.ai_socktype = (TT.udp ? SOCK_DGRAM : SOCK_STREAM);
   if ((ret = getaddrinfo(host, ptr, &hints, &res))) 
     perror_exit("%s", gai_strerror(ret));
 
@@ -245,7 +241,7 @@
 
   if (!rp) error_exit("Invalid IP %s", host);
 
-  sockfd = xsocket(rp->ai_family, TT.udp ?SOCK_DGRAM :SOCK_STREAM, 0);
+  sockfd = xsocket(rp->ai_family, TT.udp ? SOCK_DGRAM : SOCK_STREAM, 0);
   setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &set, sizeof(set));
   if (TT.udp) setsockopt(sockfd, IPPROTO_IP, IP_PKTINFO, &set, sizeof(set));
   xbind(sockfd, rp->ai_addr, rp->ai_addrlen);
@@ -256,7 +252,7 @@
 
 static void handle_signal(int sig)
 {
-  if (toys.optflags & FLAG_v) xprintf("got signal %d, exit\n", sig);
+  if (FLAG(v)) xprintf("got signal %d, exit\n", sig);
   raise(sig);
   _exit(sig + 128); //should not reach here
 } 
@@ -272,41 +268,38 @@
   char *ptr = NULL, *addr, *server, buf[sizeof(struct sockaddr_in6)];
   socklen_t len = sizeof(buf);
 
-  TT.udp = (*toys.which->name == 'u');
+  TT.udp = *toys.which->name == 'u';
   if (TT.udp) toys.optflags &= ~FLAG_C;
   memset(buf, 0, len);
-  if (toys.optflags & FLAG_C) {
-    if ((ptr = strchr(TT.nmsg, ':'))) {
-      *ptr = '\0';
-      ptr++;
-    }
-    TT.maxc = atolx_range(TT.nmsg, 1, INT_MAX);
+  if (FLAG(C)) {
+    if ((ptr = strchr(TT.C, ':'))) *ptr++ = 0;
+    TT.maxc = atolx_range(TT.C, 1, INT_MAX);
   }
   
   fd = create_bind_sock(toys.optargs[0], (struct sockaddr*)&haddr);
-  if(toys.optflags & FLAG_u) {
-    get_uidgid(&uid, &gid, TT.user);
+  if (FLAG(u)) {
+    get_uidgid(&uid, &gid, TT.u);
     setuid(uid);
     setgid(gid);
   }
 
-  if (!TT.udp && (listen(fd, TT.bn) < 0)) perror_exit("Listen failed");
+  if (!TT.udp && (listen(fd, TT.b) < 0)) perror_exit("Listen failed");
   server = sock_to_address((struct sockaddr*)&haddr, NI_NUMERICHOST|NI_NUMERICSERV);
-  if (toys.optflags & FLAG_v) {
-    if (toys.optflags & FLAG_u)
-      xprintf("%s: listening on %s, starting, uid %u, gid %u\n"
-          ,toys.which->name, server, uid, gid);
+  if (FLAG(v)) {
+    if (FLAG(u))
+      xprintf("%s: listening on %s, starting, uid %u, gid %u\n",
+        toys.which->name, server, uid, gid);
     else 
       xprintf("%s: listening on %s, starting\n", toys.which->name, server);
   }
-  for (j = 0; j < HASH_NR; j++) h[j].head = NULL;
+  for (j = 0; j < HASH_NR; j++) h[j].head = 0;
   sigatexit(handle_signal);  
   signal(SIGCHLD, handle_exit);
 
   while (1) {
-    if (TT.count_all  < TT.cn) {
+    if (TT.count_all < TT.c) {
       if (TT.udp) {
-        if(recvfrom(fd, NULL, 0, MSG_PEEK, (struct sockaddr *)buf, &len) < 0)
+        if (recvfrom(fd, 0, 0, MSG_PEEK, (void *)buf, &len) < 0)
           perror_exit("recvfrom");
         newfd = fd;
       } else {
@@ -323,12 +316,12 @@
     addr = sock_to_address((struct sockaddr*)buf, NI_NUMERICHOST);
 
     hash = haship(addr);
-    if (toys.optflags & FLAG_C) {
+    if (FLAG(C)) {
       for (head = h[hash].head; head; head = head->next)
         if (!strcmp(head->d, addr)) break;
 
       if (head && head->count >= TT.maxc) {
-        if (ptr) write(newfd, ptr, strlen(ptr)+1);
+        if (ptr) write(newfd, ptr, strlen(ptr)); // TODO: this can block
         close(newfd);
         TT.count_all--;
         continue;
@@ -353,18 +346,17 @@
 
     if (!(pid = xfork())) {
       char *serv = NULL, *clie = NULL;
-      char *client = sock_to_address((struct sockaddr*)buf, NI_NUMERICHOST | NI_NUMERICSERV);
-      if (toys.optflags & FLAG_h) { //lookup name
-        if (toys.optflags & FLAG_l) serv = xstrdup(TT.name);
-        else serv = sock_to_address((struct sockaddr*)&haddr, 0);
-        clie = sock_to_address((struct sockaddr*)buf, 0);
+      char *client = sock_to_address((void *)buf, NI_NUMERICHOST | NI_NUMERICSERV);
+      if (FLAG(h)) { //lookup name
+        serv = TT.l ? xstrdup(TT.l) : sock_to_address((void *)&haddr, 0);
+        clie = sock_to_address((void *)buf, 0);
       }
 
-      if (!(toys.optflags & FLAG_E)) {
-        setenv("PROTO", TT.udp ?"UDP" :"TCP", 1);
+      if (!FLAG(E)) {
+        setenv("PROTO", TT.udp ? "UDP" :"TCP", 1);
         setenv("PROTOLOCALADDR", server, 1);
         setenv("PROTOREMOTEADDR", client, 1);
-        if (toys.optflags & FLAG_h) {
+        if (FLAG(h)) {
           setenv("PROTOLOCALHOST", serv, 1);
           setenv("PROTOREMOTEHOST", clie, 1);
         }
@@ -374,15 +366,15 @@
           setenv("TCPCONCURRENCY", max_c, 1); //Not valid for udp
         }
       }
-      if (toys.optflags & FLAG_v) {
+      if (FLAG(v)) {
         xprintf("%s: start %d %s-%s",toys.which->name, getpid(), server, client);
-        if (toys.optflags & FLAG_h) xprintf(" (%s-%s)", serv, clie);
+        if (FLAG(h)) xprintf(" (%s-%s)", serv, clie);
         xputc('\n');
-        if (TT.cn > 1) 
-          xprintf("%s: status %d/%d\n",toys.which->name, TT.count_all, TT.cn);
+        if (TT.c > 1)
+          xprintf("%s: status %d/%ld\n",toys.which->name, TT.count_all, TT.c);
       }
       free(client);
-      if (toys.optflags & FLAG_h) {
+      if (FLAG(h)) {
         free(serv);
         free(clie);
       }
diff --git a/toys/pending/vi.c b/toys/pending/vi.c
index bbb0a90..9e743dc 100644
--- a/toys/pending/vi.c
+++ b/toys/pending/vi.c
@@ -12,9 +12,11 @@
   default n
   help
     usage: vi [-s script] FILE
-    -s script: run script file
+
     Visual text editor. Predates the existence of standardized cursor keys,
     so the controls are weird and historical.
+
+    -s script: run script file
 */
 
 #define FOR_vi
@@ -22,6 +24,8 @@
 
 GLOBALS(
   char *s;
+
+  char *filename;
   int vi_mode, tabstop, list;
   int cur_col, cur_row, scr_row;
   int drawn_row, drawn_col;
@@ -41,13 +45,9 @@
     char* data;
   } yank;
 
-  int modified;
   size_t filesize;
 // mem_block contains RO data that is either original file as mmap
 // or heap allocated inserted data
-//
-//
-//
   struct block_list {
     struct block_list *next, *prev;
     struct mem_block {
@@ -122,6 +122,7 @@
 {
   char* end = str+size;
   int pos = size, len, width = 0;
+
   for (;pos >= 0; end--, pos--) {
     len = utf8_lnw(&width, end, size-pos);
     if (len && width) return end;
@@ -168,6 +169,7 @@
   struct mem_block *b = xmalloc(sizeof(struct mem_block));
   struct slice *next = xmalloc(sizeof(struct slice));
   struct slice_list *s = TT.slices;
+
   b->size = size;
   b->len = len;
   b->alloc = type;
@@ -216,9 +218,7 @@
         (char *)next);
     } else {
       // insert after
-      s = (struct slice_list *)dlist_add_after((struct double_list **)&TT.slices,
-      (struct double_list **)&s,
-      (char *)next);
+      s = (void *)dlist_add_after((void *)&TT.slices, (void *)&s, (void *)next);
     }
   }
   return 0;
@@ -231,6 +231,7 @@
   struct slice_list *e, *s = TT.slices;
   size_t end = offset+len;
   size_t epos, spos = 0;
+
   if (!s) return -1;
 
   //find start and end slices
@@ -290,6 +291,17 @@
 
   return 0;
 }
+static int modified()
+{
+  if (TT.text->next !=  TT.text->prev) return 1;
+  if (TT.slices->next != TT.slices->prev) return 1;
+  if (!TT.text || !TT.slices) return 0;
+  if (!TT.text->node || !TT.slices->node) return 0;
+  if (TT.text->node->alloc != MMAP) return 1;
+  if (TT.text->node->len != TT.slices->node->len) return 1;
+  if (!TT.text->node->len) return 1;
+  return 0;
+}
 
 //find offset position in slices
 static struct slice_list *slice_offset(size_t *start, size_t offset)
@@ -356,11 +368,10 @@
 {
   struct slice_list *s = TT.slices;
   size_t pos = 0;
-  if (s) do {
 
+  if (s) do {
     pos += s->node->len;
     s = s->next;
-
   } while (s != TT.slices);
 
   return pos;
@@ -390,6 +401,7 @@
 {
   struct slice_list *s = TT.slices;
   size_t spos = 0;
+
   //find start
   if (!(s = slice_offset(&spos, offset))) return 0;
   return s->node->data[offset-spos];
@@ -414,6 +426,7 @@
 static size_t text_sol(size_t offset)
 {
   size_t pos;
+
   if (!TT.filesize || !offset) return 0;
   else if (TT.filesize <= offset) return TT.filesize-1;
   else if ((pos = text_strrchr(offset-1, '\n')) == SIZE_MAX) return 0;
@@ -484,6 +497,7 @@
 {
   size_t bytes, pos = offset;
   char *s = 0;
+
   do {
     bytes = text_getline(toybuf, pos, ARRAY_LEN(toybuf));
     if (!bytes) pos++; //empty line
@@ -505,6 +519,22 @@
   free(d);
 }
 
+static void show_error(char *fmt, ...)
+{
+  va_list va;
+
+  printf("\a\e[%dH\e[41m\e[37m\e[K\e[1m", TT.screen_height+1);
+  va_start(va, fmt);
+  vprintf(fmt, va);
+  va_end(va);
+  printf("\e[0m");
+  xflush(1);
+
+  // TODO: better integration with status line: remove sleep and keep
+  // message until next operation.
+  sleep(1);
+}
+
 static void linelist_unload()
 {
   llist_traverse((void *)TT.slices, llist_free_double);
@@ -512,53 +542,70 @@
   TT.slices = 0, TT.text = 0;
 }
 
-static int linelist_load(char *filename)
+static void linelist_load(char *filename, int ignore_missing)
 {
-  if (!filename) filename = (char*)*toys.optargs;
+  int fd;
+  long long size;
 
-  if (filename) {
-    int fd = open(filename, O_RDONLY);
-    long long size;
-
-    if (fd == -1 || !(size = fdlength(fd))) {
-      insert_str("", 0, 0, 0, STACK);
-      TT.filesize = 0;
-
-      return 0;
-    }
-    insert_str(xmmap(0, size, PROT_READ, MAP_SHARED, fd, 0), 0, size,size,MMAP);
-    xclose(fd);
-    TT.filesize = text_filesize();
+  if (!filename) filename = TT.filename;
+  if (!filename) {
+    // `vi` with no arguments creates a new unnamed file.
+    insert_str(xstrdup("\n"), 0, 1, 1, HEAP);
+    return;
   }
 
-  return 1;
+  fd = open(filename, O_RDONLY);
+  if (fd == -1) {
+    if (!ignore_missing)
+      show_error("Couldn't open \"%s\" for reading: %s", filename,
+          strerror(errno));
+    insert_str(xstrdup("\n"), 0, 1, 1, HEAP);
+    return;
+  }
+
+  size = fdlength(fd);
+  if (size > 0) {
+    insert_str(xmmap(0,size,PROT_READ,MAP_SHARED,fd,0), 0, size, size, MMAP);
+    TT.filesize = text_filesize();
+  } else if (!size) insert_str(xstrdup("\n"), 0, 1, 1, HEAP);
+  xclose(fd);
 }
 
-static void write_file(char *filename)
+static int write_file(char *filename)
 {
   struct slice_list *s = TT.slices;
   struct stat st;
   int fd = 0;
-  if (!s) return;
 
-  if (!filename) filename = (char*)*toys.optargs;
+  if (!modified()) show_error("Not modified");
+  if (!filename) filename = TT.filename;
+  if (!filename) {
+    show_error("No file name");
+    return -1;
+  }
+
+  if (stat(filename, &st) == -1) st.st_mode = 0644;
 
   sprintf(toybuf, "%s.swp", filename);
 
-  if ( (fd = xopen(toybuf, O_WRONLY | O_CREAT | O_TRUNC)) <0) return;
+  if ((fd = open(toybuf, O_WRONLY | O_CREAT | O_TRUNC, st.st_mode)) == -1) {
+    show_error("Couldn't open \"%s\" for writing: %s", toybuf, strerror(errno));
+    return -1;
+  }
 
-  do {
-    xwrite(fd, (void *)s->node->data, s->node->len );
-    s = s->next;
-  } while (s != TT.slices);
+  if (s) {
+    do {
+      xwrite(fd, (void *)s->node->data, s->node->len);
+      s = s->next;
+    } while (s != TT.slices);
+  }
 
   linelist_unload();
 
   xclose(fd);
-  if (!stat(filename, &st)) chmod(toybuf, st.st_mode);
-  else chmod(toybuf, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
   xrename(toybuf, filename);
-  linelist_load(filename);
+  linelist_load(filename, 0);
+  return 0;
 }
 
 //jump into valid offset index
@@ -567,8 +614,8 @@
 {
   char buf[8] = {0};
   int len, width = 0;
-  if (!TT.filesize) TT.cursor = 0;
 
+  if (!TT.filesize) TT.cursor = 0;
   for (;;) {
     if (TT.cursor < 1) {
       TT.cursor = 0;
@@ -577,11 +624,9 @@
       TT.cursor = TT.filesize-1;
       return;
     }
-    if ((len = text_codepoint(buf, TT.cursor)) < 1) {
-      TT.cursor--; //we are not in valid data try jump over
-      continue;
-    }
-    if (utf8_lnw(&width, buf, len) && width) break;
+    // if we are not in valid data try jump over
+    if ((len = text_codepoint(buf, TT.cursor)) < 1) TT.cursor--;
+    else if (utf8_lnw(&width, buf, len) && width) break;
     else TT.cursor--; //combine char jump over
   }
 }
@@ -635,7 +680,6 @@
 
   TT.scr_row = s;
   TT.cur_row = c;
-
 }
 
 //TODO search yank buffer by register
@@ -672,8 +716,7 @@
 
   vi_yank(reg, from, flags);
 
-  if (TT.vi_mov_flag&0x80000000)
-    start = TT.cursor, end = from;
+  if (TT.vi_mov_flag&0x80000000) start = TT.cursor, end = from;
 
   //pre adjust cursor move one right until at next valid rune
   if (TT.vi_mov_flag&2) {
@@ -702,6 +745,7 @@
 static int cur_left(int count0, int count1, char *unused)
 {
   int count = count0*count1;
+
   TT.vi_mov_flag |= 0x80000000;
   for (;count && TT.cursor; count--) {
     TT.cursor--;
@@ -741,8 +785,8 @@
 static int cur_up(int count0, int count1, char *unused)
 {
   int count = count0*count1;
-  for (;count--;) TT.cursor = text_psol(TT.cursor);
 
+  for (;count--;) TT.cursor = text_psol(TT.cursor);
   TT.vi_mov_flag |= 0x80000000;
   check_cursor_bounds();
   return 1;
@@ -752,6 +796,7 @@
 static int cur_down(int count0, int count1, char *unused)
 {
   int count = count0*count1;
+
   for (;count--;) TT.cursor = text_nsol(TT.cursor);
   check_cursor_bounds();
   return 1;
@@ -836,6 +881,18 @@
   return 1;
 }
 
+static int backspace(char reg, int count0, int count1)
+{
+  size_t from = 0;
+  size_t to = TT.cursor;
+  cur_left(1, 1, 0);
+  from = TT.cursor;
+  if (from != to)
+    vi_delete(reg, to, 0);
+  check_cursor_bounds();
+  return 1;
+}
+
 static int vi_movw(int count0, int count1, char *unused)
 {
   int count = count0*count1;
@@ -1011,8 +1068,7 @@
   //vi inconsistancy
   //if yank ends with \n push is linemode else push in place+1
   size_t history = TT.cursor;
-  char *start = TT.yank.data;
-  char *eol = strchr(start, '\n');
+  char *start = TT.yank.data, *eol = strchr(start, '\n');
 
   if (start[strlen(start)-1] == '\n') {
     if ((TT.cursor = text_strchr(TT.cursor, '\n')) == SIZE_MAX)
@@ -1133,24 +1189,12 @@
 //  have special cases such as dd, yy, also movements can work without
 //  CMD
 //ex commands can be even more complicated than this....
-//
-struct vi_cmd_param {
-  const char* cmd;
-  unsigned flags;
-  int (*vi_cmd)(char, size_t, int);//REG,from,FLAGS
-};
-struct vi_mov_param {
-  const char* mov;
-  unsigned flags;
-  int (*vi_mov)(int, int, char*);//COUNT0,COUNT1,params
-};
+
 //special cases without MOV and such
 struct vi_special_param {
   const char *cmd;
   int (*vi_special)(char, int, int);//REG,COUNT0,COUNT1
-};
-struct vi_special_param vi_special[] =
-{
+} vi_special[] = {
   {"D", &vi_D},
   {"I", &vi_I},
   {"J", &vi_join},
@@ -1162,11 +1206,12 @@
   {"dd", &vi_dd},
   {"yy", &vi_yy},
 };
-//there is around ~47 vi moves
-//some of them need extra params
-//such as f and '
-struct vi_mov_param vi_movs[] =
-{
+//there is around ~47 vi moves, some of them need extra params such as f and '
+struct vi_mov_param {
+  const char* mov;
+  unsigned flags;
+  int (*vi_mov)(int, int, char*);//COUNT0,COUNT1,params
+} vi_movs[] = {
   {"0", 0, &vi_zero},
   {"b", 0, &vi_movb},
   {"e", 0, &vi_move},
@@ -1188,8 +1233,11 @@
 //also dw stops at w position and cw seem to stop at e pos+1...
 //so after movement we need to possibly set up some flags before executing
 //command, and command needs to adjust...
-struct vi_cmd_param vi_cmds[] =
-{
+struct vi_cmd_param {
+  const char* cmd;
+  unsigned flags;
+  int (*vi_cmd)(char, size_t, int);//REG,from,FLAGS
+} vi_cmds[] = {
   {"c", 1, &vi_change},
   {"d", 1, &vi_delete},
   {"y", 1, &vi_yank},
@@ -1199,16 +1247,14 @@
 {
   int i = 0, val = 0;
   char *cmd_e;
-  int (*vi_cmd)(char, size_t, int) = 0;
-  int (*vi_mov)(int, int, char*) = 0;
+  int (*vi_cmd)(char, size_t, int) = 0, (*vi_mov)(int, int, char*) = 0;
 
   TT.count0 = 0, TT.count1 = 0, TT.vi_mov_flag = 0;
   TT.vi_reg = '"';
 
   if (*cmd == '"') {
     cmd++;
-    TT.vi_reg = *cmd; //TODO check validity
-    cmd++;
+    TT.vi_reg = *cmd++; //TODO check validity
   }
   errno = 0;
   val = strtol(cmd, &cmd_e, 10);
@@ -1216,11 +1262,9 @@
   else cmd = cmd_e;
   TT.count0 = val;
 
-  for (i = 0; i < ARRAY_LEN(vi_special); i++) {
-    if (strstr(cmd, vi_special[i].cmd)) {
+  for (i = 0; i < ARRAY_LEN(vi_special); i++)
+    if (strstr(cmd, vi_special[i].cmd))
       return vi_special[i].vi_special(TT.vi_reg, TT.count0, TT.count1);
-    }
-  }
 
   for (i = 0; i < ARRAY_LEN(vi_cmds); i++) {
     if (!strncmp(cmd, vi_cmds[i].cmd, strlen(vi_cmds[i].cmd))) {
@@ -1255,39 +1299,31 @@
 }
 
 
+// Return non-zero to exit.
 static int run_ex_cmd(char *cmd)
 {
-  if (cmd[0] == '/') {
-    search_str(&cmd[1]);
-  } else if (cmd[0] == '?') {
+  if (cmd[0] == '/') search_str(cmd+1);
+  else if (cmd[0] == '?') {
     // TODO: backwards search.
   } else if (cmd[0] == ':') {
     if (!strcmp(&cmd[1], "q") || !strcmp(&cmd[1], "q!")) {
-      // TODO: if no !, check whether file modified.
-      //exit_application;
-      return -1;
-    }
-    else if (strstr(&cmd[1], "wq")) {
-      write_file(0);
-      return -1;
-    }
-    else if (strstr(&cmd[1], "w")) {
-      write_file(0);
-      return 1;
-    }
-    else if (strstr(&cmd[1], "set list")) {
+      if (cmd[2] != '!' && modified())
+        show_error("Unsaved changes (\"q!\" to ignore)");
+      else return 1;
+    } else if (strstr(cmd+1, "w ")) write_file(&cmd[3]);
+    else if (strstr(cmd+1, "wq")) {
+      if (!write_file(0)) return 1;
+      show_error("Unsaved changes (\"q!\" to ignore)");
+    } else if (strstr(cmd+1, "w")) write_file(0);
+    else if (strstr(cmd+1, "set list")) {
       TT.list = 1;
       TT.vi_mov_flag |= 0x30000000;
-      return 1;
-    }
-    else if (strstr(&cmd[1], "set nolist")) {
+    } else if (strstr(cmd+1, "set nolist")) {
       TT.list = 0;
       TT.vi_mov_flag |= 0x30000000;
-      return 1;
     }
   }
   return 0;
-
 }
 
 static int vi_crunch(FILE *out, int cols, int wc)
@@ -1344,21 +1380,12 @@
 static void draw_page()
 {
   unsigned y = 0;
-  int x = 0;
-
+  int x = 0, bytes = 0;
   char *line = 0, *end = 0;
-  int bytes = 0;
-
   //screen coordinates for cursor
   int cy_scr = 0, cx_scr = 0;
-
   //variables used only for cursor handling
-  int aw = 0, iw = 0, clip = 0, margin = 8;
-
-  int scroll = 0, redraw = 0;
-
-  int SSOL, SOL;
-
+  int aw = 0, iw = 0, clip = 0, margin = 8, scroll = 0, redraw = 0, SSOL, SOL;
 
   adjust_screen_buffer();
   //redraw = 3; //force full redraw
@@ -1493,7 +1520,7 @@
 
 void vi_main(void)
 {
-  char stdout_buf[BUFSIZ];
+  char stdout_buf[8192];
   char keybuf[16] = {0};
   char vi_buf[16] = {0};
   char utf8_code[8] = {0};
@@ -1506,7 +1533,8 @@
 
   TT.il->alloc = 80, TT.yank.alloc = 128;
 
-  linelist_load(0);
+  TT.filename = *toys.optargs;
+  linelist_load(0, 1);
 
   TT.vi_mov_flag = 0x20000000;
   TT.vi_mode = 1, TT.tabstop = 8;
@@ -1516,7 +1544,7 @@
   TT.screen_height -= 1;
 
   // Avoid flicker.
-  setbuf(stdout, stdout_buf);
+  setbuffer(stdout, stdout_buf, sizeof(stdout_buf));
 
   xsignal(SIGWINCH, generic_signal);
   set_terminal(0, 1, 0, 0);
@@ -1548,6 +1576,12 @@
     // TODO: support cursor keys in ex mode too.
     if (TT.vi_mode && key>=256) {
       key -= 256;
+      //if handling arrow keys insert what ever is in input buffer before moving
+      if (TT.il->len) {
+          i_insert(TT.il->data, TT.il->len);
+          TT.il->len = 0;
+          memset(TT.il->data, 0, TT.il->alloc);
+      }
       if (key==KEY_UP) cur_up(1, 1, 0);
       else if (key==KEY_DOWN) cur_down(1, 1, 0);
       else if (key==KEY_LEFT) cur_left(1, 1, 0);
@@ -1594,6 +1628,10 @@
           vi_buf[0] = 0;
           vi_buf_pos = 0;
           break;
+        case 0x7F: //FALLTHROUGH
+        case 0x08:
+          backspace(TT.vi_reg, 1, 1);
+          break;
         default:
           if (key > 0x20 && key < 0x7B) {
             vi_buf[vi_buf_pos] = key;//TODO handle input better
@@ -1627,8 +1665,7 @@
           break;
         case 0x0A:
         case 0x0D:
-          if (run_ex_cmd(TT.il->data) == -1)
-            goto cleanup_vi;
+          if (run_ex_cmd(TT.il->data)) goto cleanup_vi;
           TT.vi_mode = 1;
           TT.il->len = 0;
           memset(TT.il->data, 0, TT.il->alloc);
@@ -1660,12 +1697,11 @@
             int shrink = strlen(last);
             memset(last, 0, shrink);
             TT.il->len -= shrink;
-          }
+          } else backspace(TT.vi_reg, 1, 1);
           break;
         case 0x0A:
         case 0x0D:
           //insert newline
-          //
           TT.il->data[TT.il->len++] = '\n';
           i_insert(TT.il->data, TT.il->len);
           TT.il->len = 0;
@@ -1673,8 +1709,8 @@
           break;
         default:
           if ((key >= 0x20 || key == 0x09) &&
-              utf8_dec(key, utf8_code, &utf8_dec_p)) {
-
+              utf8_dec(key, utf8_code, &utf8_dec_p))
+          {
             if (TT.il->len+utf8_dec_p+1 >= TT.il->alloc) {
               TT.il->data = realloc(TT.il->data, TT.il->alloc*2);
               TT.il->alloc *= 2;
@@ -1683,7 +1719,6 @@
             TT.il->len += utf8_dec_p;
             utf8_dec_p = 0;
             *utf8_code = 0;
-
           }
           break;
       }
diff --git a/toys/posix/cat.c b/toys/posix/cat.c
index 6daba7a..1eb15d4 100644
--- a/toys/posix/cat.c
+++ b/toys/posix/cat.c
@@ -3,48 +3,23 @@
  * Copyright 2006 Rob Landley <rob@landley.net>
  *
  * See http://opengroup.org/onlinepubs/9699919799/utilities/cat.html
- *
- * And "Cat -v considered harmful" at
- *   http://cm.bell-labs.com/cm/cs/doc/84/kp.ps.gz
 
-USE_CAT(NEWTOY(cat, "u"USE_CAT_V("vte"), TOYFLAG_BIN))
-USE_CATV(NEWTOY(catv, USE_CATV("vte"), TOYFLAG_USR|TOYFLAG_BIN))
+USE_CAT(NEWTOY(cat, "uvte", TOYFLAG_BIN))
 
 config CAT
   bool "cat"
   default y
   help
-    usage: cat [-u] [FILE...]
+    usage: cat [-etuv] [FILE...]
 
     Copy (concatenate) files to stdout.  If no files listed, copy from stdin.
     Filename "-" is a synonym for stdin.
 
-    -u	Copy one byte at a time (slow)
-
-config CAT_V
-  bool "cat -etv"
-  default n
-  depends on CAT
-  help
-    usage: cat [-evt]
-
     -e	Mark each newline with $
     -t	Show tabs as ^I
+    -u	Copy one byte at a time (slow)
     -v	Display nonprinting characters as escape sequences with M-x for
     	high ascii characters (>127), and ^x for other nonprinting chars
-
-config CATV
-  bool "catv"
-  default y
-  help
-    usage: catv [-evt] [FILE...]
-
-    Display nonprinting characters as escape sequences. Use M-x for
-    high ascii characters (>127), and ^x for other nonprinting chars.
-
-    -e	Mark each newline with $
-    -t	Show tabs as ^I
-    -v	Don't use ^x or M-x escapes
 */
 
 #define FOR_cat
@@ -53,21 +28,18 @@
 
 static void do_cat(int fd, char *name)
 {
-  int i, len, size=(toys.optflags & FLAG_u) ? 1 : sizeof(toybuf);
+  int i, len, size = FLAG(u) ? 1 : sizeof(toybuf);
 
   for(;;) {
     len = read(fd, toybuf, size);
-    if (len < 0) {
-      toys.exitval = EXIT_FAILURE;
-      perror_msg_raw(name);
-    }
-    if (len < 1) break;
-    if ((CFG_CAT_V || CFG_CATV) && (toys.optflags&~FLAG_u)) {
-      for (i=0; i<len; i++) {
-        char c=toybuf[i];
+    if (len<0) perror_msg_raw(name);
+    if (len<1) break;
+    if (toys.optflags&~FLAG_u) {
+      for (i = 0; i<len; i++) {
+        char c = toybuf[i];
 
-        if (c > 126 && (toys.optflags & FLAG_v)) {
-          if (c > 127) {
+        if (c>126 && FLAG(v)) {
+          if (c>127) {
             printf("M-");
             c -= 128;
           }
@@ -76,9 +48,9 @@
             continue;
           }
         }
-        if (c < 32) {
+        if (c<32) {
           if (c == 10) {
-            if (toys.optflags & FLAG_e) xputc('$');
+            if (FLAG(e)) xputc('$');
           } else if (toys.optflags & (c==9 ? FLAG_t : FLAG_v)) {
             printf("^%c", c+'@');
             continue;
@@ -94,9 +66,3 @@
 {
   loopfiles(toys.optargs, do_cat);
 }
-
-void catv_main(void)
-{
-  toys.optflags ^= FLAG_v;
-  loopfiles(toys.optargs, do_cat);
-}
diff --git a/toys/posix/chgrp.c b/toys/posix/chgrp.c
index a63272a..73c4b22 100644
--- a/toys/posix/chgrp.c
+++ b/toys/posix/chgrp.c
@@ -44,24 +44,24 @@
 
 static int do_chgrp(struct dirtree *node)
 {
-  int fd, ret, flags = toys.optflags;
+  int fd, ret;
 
   // Depth first search
   if (!dirtree_notdotdot(node)) return 0;
-  if ((flags & FLAG_R) && !node->again && S_ISDIR(node->st.st_mode))
-    return DIRTREE_COMEAGAIN|(DIRTREE_SYMFOLLOW*!!(flags&FLAG_L));
+  if (FLAG(R) && !node->again && S_ISDIR(node->st.st_mode))
+    return DIRTREE_COMEAGAIN|DIRTREE_SYMFOLLOW*FLAG(L);
 
   fd = dirtree_parentfd(node);
   ret = fchownat(fd, node->name, TT.owner, TT.group,
-    AT_SYMLINK_NOFOLLOW*(!(flags&(FLAG_L|FLAG_H)) && (flags&(FLAG_h|FLAG_R))));
+    AT_SYMLINK_NOFOLLOW*(!(FLAG(L)|FLAG(H)) && (FLAG(h)|FLAG(R))));
 
-  if (ret || (flags & FLAG_v)) {
+  if (ret || FLAG(v)) {
     char *path = dirtree_path(node, 0);
-    if (flags & FLAG_v)
+    if (FLAG(v))
       xprintf("%s %s%s%s %s\n", toys.which->name, TT.owner_name,
         (toys.which->name[2]=='o' && *TT.group_name) ? ":" : "",
         TT.group_name, path);
-    if (ret == -1 && !(toys.optflags & FLAG_f))
+    if (ret == -1 && !FLAG(f))
       perror_msg("'%s' to '%s:%s'", path, TT.owner_name, TT.group_name);
     free(path);
   }
@@ -94,8 +94,7 @@
     TT.group = xgetgid(TT.group_name);
 
   for (s=toys.optargs+1; *s; s++)
-    dirtree_flagread(*s, DIRTREE_SYMFOLLOW*!!(toys.optflags&(FLAG_H|FLAG_L)),
-      do_chgrp);
+    dirtree_flagread(*s, DIRTREE_SYMFOLLOW*(FLAG(H)|FLAG(L)), do_chgrp);
 
   if (CFG_TOYBOX_FREE && ischown) free(own);
 }
diff --git a/toys/posix/cksum.c b/toys/posix/cksum.c
index 6e5b915..8bb6f81 100644
--- a/toys/posix/cksum.c
+++ b/toys/posix/cksum.c
@@ -39,24 +39,23 @@
   unsigned crc_table[256];
 )
 
-static unsigned cksum_be(unsigned crc, unsigned char c)
+static unsigned cksum_be(unsigned crc, char c)
 {
-  return (crc<<8)^TT.crc_table[(crc>>24)^c];
+  return (crc<<8) ^ TT.crc_table[(crc>>24)^c];
 }
 
-static unsigned cksum_le(unsigned crc, unsigned char c)
+static unsigned cksum_le(unsigned crc, char c)
 {
   return TT.crc_table[(crc^c)&0xff] ^ (crc>>8);
 }
 
 static void do_cksum(int fd, char *name)
 {
-  unsigned crc = (toys.optflags & FLAG_P) ? 0xffffffff : 0;
-  uint64_t llen = 0, llen2;
-  unsigned (*cksum)(unsigned crc, unsigned char c);
+  unsigned (*cksum)(unsigned crc, char c), crc = FLAG(P) ? ~0 : 0;
+  unsigned long long llen = 0, llen2;
   int len, i;
 
-  cksum = (toys.optflags & FLAG_L) ? cksum_le : cksum_be;
+  cksum = FLAG(L) ? cksum_le : cksum_be;
   // CRC the data
 
   for (;;) {
@@ -65,29 +64,22 @@
     if (len<1) break;
 
     llen += len;
-    for (i=0; i<len; i++) crc=cksum(crc, toybuf[i]);
+    for (i = 0; i<len; i++) crc = cksum(crc, toybuf[i]);
   }
 
   // CRC the length
 
-  llen2 = llen;
-  if (!(toys.optflags & FLAG_N)) {
-    while (llen) {
-      crc = cksum(crc, llen);
-      llen >>= 8;
-    }
-  }
+  if (!FLAG(N)) for (llen2 = llen; llen2; llen2 >>= 8) crc = cksum(crc, llen2);
 
-  printf((toys.optflags & FLAG_H) ? "%08x" : "%u",
-    (toys.optflags & FLAG_I) ? crc : ~crc);
-  if (!(toys.optflags&FLAG_N)) printf(" %"PRIu64, llen2);
+  printf(FLAG(H) ? "%08x" : "%u", FLAG(I) ? crc : ~crc);
+  if (!FLAG(N)) printf(" %llu", llen);
   if (toys.optc) printf(" %s", name);
   xputc('\n');
 }
 
 void cksum_main(void)
 {
-  crc_init(TT.crc_table, toys.optflags & FLAG_L);
+  crc_init(TT.crc_table, FLAG(L));
   loopfiles(toys.optargs, do_cksum);
 }
 
diff --git a/toys/posix/cmp.c b/toys/posix/cmp.c
index 8e33c92..2621e25 100644
--- a/toys/posix/cmp.c
+++ b/toys/posix/cmp.c
@@ -34,11 +34,10 @@
 static void do_cmp(int fd, char *name)
 {
   int i, len1, len2, min_len, size = sizeof(toybuf)/2;
-  long byte_no = 1, line_no = 1;
+  long long byte_no = 1, line_no = 1;
   char *buf2 = toybuf+size;
 
-  if (toys.optc>(i = 2+!!TT.fd) && lskip(fd, atolx(toys.optargs[i])))
-    error_exit("EOF on %s", name);
+  if (toys.optc>(i = 2+!!TT.fd)) lskip(fd, atolx(toys.optargs[i]));
 
   // First time through, cache the data and return.
   if (!TT.fd) {
@@ -51,17 +50,17 @@
 
   toys.exitval = 0;
 
-  for (;!FLAG(n) || TT.n;) {
+  while (!FLAG(n) || TT.n) {
     if (FLAG(n)) TT.n -= size = minof(size, TT.n);
     len1 = readall(TT.fd, toybuf, size);
     len2 = readall(fd, buf2, size);
     min_len = minof(len1, len2);
-    for (i=0; i<min_len; i++) {
+    for (i = 0; i<min_len; i++) {
       if (toybuf[i] != buf2[i]) {
         toys.exitval = 1;
-        if (FLAG(l)) printf("%ld %o %o\n", byte_no, toybuf[i], buf2[i]);
+        if (FLAG(l)) printf("%lld %o %o\n", byte_no, toybuf[i], buf2[i]);
         else {
-          if (!FLAG(s)) printf("%s %s differ: char %ld, line %ld\n",
+          if (!FLAG(s)) printf("%s %s differ: char %lld, line %lld\n",
               TT.name, name, byte_no, line_no);
           goto out;
         }
@@ -70,8 +69,11 @@
       if (toybuf[i] == '\n') line_no++;
     }
     if (len1 != len2) {
-      if (!FLAG(s)) error_msg("EOF on %s", len1 < len2 ? TT.name : name);
-      else toys.exitval = 1;
+      if (!FLAG(s)) {
+        strcpy(toybuf, "EOF on %s after byte %lld, line %lld");
+        if (FLAG(l)) *strchr(toybuf, ',') = 0;
+        error_msg(toybuf, len1 < len2 ? TT.name : name, byte_no-1, line_no-1);
+      } else toys.exitval = 1;
       break;
     }
     if (len1 < 1) break;
@@ -84,6 +86,6 @@
 void cmp_main(void)
 {
   toys.exitval = 2;
-  loopfiles_rw(toys.optargs, O_CLOEXEC|(WARN_ONLY*!FLAG(s)), 0, do_cmp);
+  loopfiles_rw(toys.optargs, O_CLOEXEC|WARN_ONLY*!FLAG(s), 0, do_cmp);
   if (toys.optc == 1) do_cmp(0, "-");
 }
diff --git a/toys/posix/comm.c b/toys/posix/comm.c
index 2d118b7..9135924 100644
--- a/toys/posix/comm.c
+++ b/toys/posix/comm.c
@@ -43,26 +43,26 @@
 {
   FILE *file[2];
   char *line[2];
-  int i;
+  int i = 0;
 
-  if (toys.optflags == 7) return;
-
-  for (i = 0; i < 2; i++) {
-    file[i] = xfopen(toys.optargs[i], "r");
+  for (i = 0; i<2; i++) {
+    file[i] = strcmp(toys.optargs[i], "-")?xfopen(toys.optargs[i], "r"):stdin;
     line[i] = xgetline(file[i]);
   }
 
+  if (toys.optflags == 7) return;
+
   while (line[0] && line[1]) {
     int order = strcmp(line[0], line[1]);
 
-    if (order == 0) {
+    if (!order) {
       writeline(line[0], 2);
       for (i = 0; i < 2; i++) {
         free(line[i]);
         line[i] = xgetline(file[i]);
       }
     } else {
-      i = order < 0 ? 0 : 1;
+      i = order>0;
       writeline(line[i], i);
       free(line[i]);
       line[i] = xgetline(file[i]);
@@ -76,5 +76,5 @@
     line[i] = xgetline(file[i]);
   }
 
-  if (CFG_TOYBOX_FREE) for (i = 0; i < 2; i++) fclose(file[i]);
+  if (CFG_TOYBOX_FREE) fclose(file[0]), fclose(file[1]);
 }
diff --git a/toys/posix/cp.c b/toys/posix/cp.c
index 7b9889a..c11da16 100644
--- a/toys/posix/cp.c
+++ b/toys/posix/cp.c
@@ -16,8 +16,8 @@
 // for FLAG macros to work out right in shared infrastructure.
 
 USE_CP(NEWTOY(cp, "<1(preserve):;D(parents)RHLPprudaslvnF(remove-destination)fit:T[-HLPd][-niu][+Rr]", TOYFLAG_BIN))
-USE_MV(NEWTOY(mv, "<1vnF(remove-destination)fit:T[-ni]", TOYFLAG_BIN))
-USE_INSTALL(NEWTOY(install, "<1cdDpsvt:m:o:g:", TOYFLAG_USR|TOYFLAG_BIN))
+USE_MV(NEWTOY(mv, "<1v(verbose)nF(remove-destination)fit:T[-ni]", TOYFLAG_BIN))
+USE_INSTALL(NEWTOY(install, "<1cdDp(preserve-timestamps)svt:m:o:g:", TOYFLAG_USR|TOYFLAG_BIN))
 
 config CP
   bool "cp"
@@ -148,10 +148,8 @@
 
     // Detect recursive copies via repeated top node (cp -R .. .) or
     // identical source/target (fun with hardlinks).
-    if ((TT.top.st_dev == try->st.st_dev && TT.top.st_ino == try->st.st_ino
-         && (catch = TT.destname))
-        || (!fstatat(cfd, catch, &cst, 0) && cst.st_dev == try->st.st_dev
-         && cst.st_ino == try->st.st_ino))
+    if ((same_file(&TT.top, &try->st) && (catch = TT.destname))
+        || (!fstatat(cfd, catch, &cst, 0) && same_file(&cst, &try->st)))
     {
       error_msg("'%s' is '%s'", catch, err = dirtree_path(try, 0));
       free(err);
@@ -206,7 +204,7 @@
         if (!mkdirat(cfd, catch, try->st.st_mode | 0200) || errno == EEXIST)
           if (-1 != (try->extra = openat(cfd, catch, O_NOFOLLOW)))
             if (!fstat(try->extra, &st2) && S_ISDIR(st2.st_mode))
-              return DIRTREE_COMEAGAIN | (DIRTREE_SYMFOLLOW*!!FLAG(L));
+              return DIRTREE_COMEAGAIN | DIRTREE_SYMFOLLOW*FLAG(L);
 
       // Hardlink
 
@@ -432,9 +430,7 @@
     // "mv across devices" triggers cp fallback path, so set that as default
     errno = EXDEV;
     if (CFG_MV && toys.which->name[0] == 'm') {
-      int force = FLAG(f), no_clobber = FLAG(n);
-
-      if (!force || no_clobber) {
+      if (!FLAG(f) || FLAG(n)) {
         struct stat st;
         int exists = !stat(TT.destname, &st);
 
@@ -447,7 +443,7 @@
           else unlink(TT.destname);
         }
         // if -n and dest exists, don't try to rename() or copy
-        if (exists && no_clobber) send = 0;
+        if (exists && FLAG(n)) send = 0;
       }
       if (send) send = rename(src, TT.destname);
       if (trail) trail[1] = '/';
@@ -456,7 +452,7 @@
     // Copy if we didn't mv or hit an error, skipping nonexistent sources
     if (send) {
       if (errno!=EXDEV || dirtree_flagread(src, DIRTREE_SHUTUP+
-        DIRTREE_SYMFOLLOW*!!(FLAG(H)||FLAG(L)), TT.callback))
+        DIRTREE_SYMFOLLOW*(FLAG(H)|FLAG(L)), TT.callback))
           perror_msg("bad '%s'", src);
     }
     if (destdir) free(TT.destname);
@@ -472,9 +468,9 @@
 
 // Export cp flags into install's flag context.
 
-static inline int cp_flag_F(void) { return FLAG_F; };
-static inline int cp_flag_p(void) { return FLAG_p; };
-static inline int cp_flag_v(void) { return FLAG_v; };
+static inline int cp_flag_F(void) { return FLAG_F; }
+static inline int cp_flag_p(void) { return FLAG_p; }
+static inline int cp_flag_v(void) { return FLAG_v; }
 
 // Switch to install's flag context
 #define FOR_install
@@ -516,15 +512,15 @@
   }
 
   if (FLAG(D)) {
-    char *destname = FLAG(t) ? TT.i.t : (TT.destname = toys.optargs[toys.optc-1]);
-    if (mkpathat(AT_FDCWD, destname, 0777, MKPATHAT_MAKE | (FLAG(t) ? MKPATHAT_MKLAST : 0)))
+    char *destname = TT.i.t ? : (TT.destname = toys.optargs[toys.optc-1]);
+    if (mkpathat(AT_FDCWD, destname, 0777, MKPATHAT_MAKE|MKPATHAT_MKLAST*FLAG(t)))
       perror_exit("-D '%s'", destname);
     if (toys.optc == !FLAG(t)) return;
   }
 
   // Translate flags from install to cp
-  toys.optflags = cp_flag_F() + cp_flag_v()*!!FLAG(v)
-    + cp_flag_p()*!!(FLAG(p)|FLAG(o)|FLAG(g));
+  toys.optflags = cp_flag_F() + cp_flag_v()*FLAG(v)
+    + cp_flag_p()*(FLAG(p)|FLAG(o)|FLAG(g));
 
   TT.callback = install_node;
   cp_main();
diff --git a/toys/posix/cpio.c b/toys/posix/cpio.c
index 5ecd56d..bbcde4b 100644
--- a/toys/posix/cpio.c
+++ b/toys/posix/cpio.c
@@ -13,36 +13,39 @@
  * In order: magic ino mode uid gid nlink mtime filesize devmajor devminor
  * rdevmajor rdevminor namesize check
  * This is the equivalent of mode -H newc in other implementations.
+ * We always do --quiet, but accept it as a compatibility NOP.
  *
- * todo: export/import linux file list text format ala gen_initramfs_list.sh
+ * TODO: export/import linux file list text format ala gen_initramfs_list.sh
+ * TODO: hardlink support, -A, -0, -a, -L, --sparse
+ * TODO: --renumber-archives (probably always?) --ignore-devno --reproducible
 
-USE_CPIO(NEWTOY(cpio, "(ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]", TOYFLAG_BIN))
+USE_CPIO(NEWTOY(cpio, "(ignore-devno)(renumber-inodes)(quiet)(no-preserve-owner)R(owner):md(make-directories)uH:p|i|t|F:v(verbose)o|[!pio][!pot][!pF]", TOYFLAG_BIN))
 
 config CPIO
   bool "cpio"
   default y
   help
-    usage: cpio -{o|t|i|p DEST} [-v] [--verbose] [-F FILE] [--no-preserve-owner]
-           [ignored: -m -H newc]
+    usage: cpio -{o|t|i|p DEST} [-v] [--verbose] [-F FILE] [-R [USER][:GROUP] [--no-preserve-owner]
 
     Copy files into and out of a "newc" format cpio archive.
 
+    -d	Create directories if needed
     -F FILE	Use archive FILE instead of stdin/stdout
-    -p DEST	Copy-pass mode, copy stdin file list to directory DEST
     -i	Extract from archive into file system (stdin=archive)
     -o	Create archive (stdin=list of files, stdout=archive)
+    -p DEST	Copy-pass mode, copy stdin file list to directory DEST
+    -R USER	Replace owner with USER[:GROUP]
     -t	Test files (list only, stdin=archive, stdout=list of files)
-    -d	Create directories if needed
-    -u	unlink existing files when extracting
+    -u	Unlink existing files when extracting
     -v	Verbose
-    --no-preserve-owner (don't set ownership during extract)
+    --no-preserve-owner     Don't set ownership during extract
 */
 
 #define FOR_cpio
 #include "toys.h"
 
 GLOBALS(
-  char *F, *H;
+  char *F, *H, *R;
 )
 
 // Read strings, tail padded to 4 byte alignment. Argument "align" is amount
@@ -80,9 +83,21 @@
 
 void cpio_main(void)
 {
-  // Subtle bit: FLAG_o is 1 so we can just use it to select stdin/stdout.
-  int pipe, afd = FLAG(o), empty = 1;
+  int pipe, afd = FLAG(o), reown = !geteuid() && !FLAG(no_preserve_owner),
+      empty = 1;
   pid_t pid = 0;
+  long Ruid = -1, Rgid = -1;
+  char *tofree = 0;
+
+  if (TT.R) {
+    char *group = TT.R+strcspn(TT.R, ":.");
+
+    if (*group) {
+      Rgid = xgetgid(group+1);
+      *group = 0;
+    }
+    if (group != TT.R) Ruid = xgetuid(TT.R);
+  }
 
   // In passthrough mode, parent stays in original dir and generates archive
   // to pipe, child does chdir to new dir and reads archive from stdin (pipe).
@@ -90,7 +105,7 @@
     if (FLAG(d)) {
       if (!*toys.optargs) error_exit("need directory for -p");
       if (mkdir(*toys.optargs, 0700) == -1 && errno != EEXIST)
-        perror_exit("mkdir %s", *toys.optargs);
+        perror_msg("mkdir %s", *toys.optargs);
     }
     if (toys.stacktop) {
       // xpopen() doesn't return from child due to vfork(), instead restarts
@@ -113,10 +128,12 @@
   // read cpio archive
 
   if (FLAG(i) || FLAG(t)) for (;; empty = 0) {
-    char *name, *tofree, *data;
+    char *name, *data;
     unsigned mode, uid, gid, timestamp;
     int test = FLAG(t), err = 0, size = 0, len;
 
+    free(tofree);
+    tofree = 0;
     // read header, skipping arbitrary leading NUL bytes (concatenated archives)
     for (;;) {
       if (1>(len = readall(afd, toybuf+size, 110-size))) break;
@@ -132,12 +149,10 @@
       if (empty) error_exit("empty archive");
       else break;
     }
-    if (size != 110 || memcmp(toybuf, "070701", 6)) error_exit("bad header");
+    if (size != 110 || smemcmp(toybuf, "070701", 6)) error_exit("bad header");
     tofree = name = strpad(afd, x8u(toybuf+94), 110);
-    if (!strcmp("TRAILER!!!", name)) {
-      free(tofree);
-      continue;
-    }
+    // TODO: this flushes hardlink detection via major/minor/ino match
+    if (!strcmp("TRAILER!!!", name)) continue;
 
     // If you want to extract absolute paths, "cd /" and run cpio.
     while (*name == '/') name++;
@@ -145,8 +160,8 @@
 
     size = x8u(toybuf+54);
     mode = x8u(toybuf+14);
-    uid = x8u(toybuf+22);
-    gid = x8u(toybuf+30);
+    uid = (Ruid>=0) ? Ruid : x8u(toybuf+22);
+    gid = (Rgid>=0) ? Rgid : x8u(toybuf+30);
     timestamp = x8u(toybuf+46); // unsigned 32 bit, so year 2100 problem
 
     // (This output is unaffected by --quiet.)
@@ -163,16 +178,23 @@
     // properly aligned with next file.
 
     if (S_ISDIR(mode)) {
-      if (!test) err = mkdir(name, mode) && !FLAG(u);
-    } else if (S_ISLNK(mode)) {
-      data = strpad(afd, size, 0);
-      if (!test) {
-        err = symlink(data, name);
-        // Can't get a filehandle to a symlink, so do special chown
-        if (!err && !geteuid() && !FLAG(no_preserve_owner))
-          err = lchown(name, uid, gid);
+      if (test) continue;
+      err = mkdir(name, mode) && (errno != EEXIST && !FLAG(u));
+
+      // Creading dir/dev doesn't give us a filehandle, we have to refer to it
+      // by name to chown/utime, but how do we know it's the same item?
+      // Check that we at least have the right type of entity open, and do
+      // NOT restore dropped suid bit in this case.
+      if (S_ISDIR(mode) && reown) {
+        int fd = open(name, O_RDONLY|O_NOFOLLOW);
+        struct stat st;
+
+        if (fd != -1 && !fstat(fd, &st) && (st.st_mode&S_IFMT) == (mode&S_IFMT))
+          err = fchown(fd, uid, gid);
+        else err = 1;
+
+        close(fd);
       }
-      free(data);
     } else if (S_ISREG(mode)) {
       int fd = test ? 0 : open(name, O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, mode);
 
@@ -197,46 +219,33 @@
 
       if (!test) {
         // set owner, restore dropped suid bit
-        if (!geteuid() && !FLAG(no_preserve_owner)) {
-          err = fchown(fd, uid, gid);
-          if (!err) err = fchmod(fd, mode);
-        }
+        if (reown) err = fchown(fd, uid, gid) && fchmod(fd, mode);
         close(fd);
       }
-    } else if (!test)
-      err = mknod(name, mode, dev_makedev(x8u(toybuf+78), x8u(toybuf+86)));
+    } else {
+      data = S_ISLNK(mode) ? strpad(afd, size, 0) : 0;
+      if (!test) {
+        err = data ? symlink(data, name)
+          : mknod(name, mode, dev_makedev(x8u(toybuf+78), x8u(toybuf+86)));
 
-    // Set ownership and timestamp.
+        // Can't get a filehandle to a symlink or a node on nodev mount,
+        // so do special chown that at least doesn't follow symlinks.
+        // We also don't chmod after, so dropped suid bit isn't restored
+        if (!err && reown) err = lchown(name, uid, gid);
+      }
+      free(data);
+    }
+
+    // Set timestamp.
     if (!test && !err) {
-      // Creading dir/dev doesn't give us a filehandle, we have to refer to it
-      // by name to chown/utime, but how do we know it's the same item?
-      // Check that we at least have the right type of entity open, and do
-      // NOT restore dropped suid bit in this case.
-      if (!S_ISREG(mode) && !S_ISLNK(mode) && !geteuid()
-          && !FLAG(no_preserve_owner))
-      {
-        int fd = open(name, O_RDONLY|O_NOFOLLOW);
-        struct stat st;
+      struct timespec times[2];
 
-        if (fd != -1 && !fstat(fd, &st) && (st.st_mode&S_IFMT) == (mode&S_IFMT))
-          err = fchown(fd, uid, gid);
-        else err = 1;
-
-        close(fd);
-      }
-
-      // set timestamp
-      if (!err) {
-        struct timespec times[2];
-
-        memset(times, 0, sizeof(struct timespec)*2);
-        times[0].tv_sec = times[1].tv_sec = timestamp;
-        err = utimensat(AT_FDCWD, name, times, AT_SYMLINK_NOFOLLOW);
-      }
+      memset(times, 0, sizeof(struct timespec)*2);
+      times[0].tv_sec = times[1].tv_sec = timestamp;
+      err = utimensat(AT_FDCWD, name, times, AT_SYMLINK_NOFOLLOW);
     }
 
     if (err) perror_msg_raw(name);
-    free(tofree);
 
   // Output cpio archive
 
@@ -266,6 +275,8 @@
       // encrypted filesystems can stat the wrong link size
       if (link) st.st_size = strlen(link);
 
+      if (Ruid>=0) st.st_uid = Ruid;
+      if (Rgid>=0) st.st_gid = Rgid;
       if (FLAG(no_preserve_owner)) st.st_uid = st.st_gid = 0;
       if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) st.st_size = 0;
       if (st.st_size >> 32) perror_msg("skipping >2G file '%s'", name);
diff --git a/toys/posix/cut.c b/toys/posix/cut.c
index c4f34f9..b9710ea 100644
--- a/toys/posix/cut.c
+++ b/toys/posix/cut.c
@@ -8,9 +8,9 @@
  * "-" counts as start to end. Using spaces to separate a comma-separated list
  * is silly and inconsistent with dd, ps, cp, and mount.
  *
- * todo: -n, -s with -c
+ * TODO: -s with -c
 
-USE_CUT(NEWTOY(cut, "b*|c*|f*|F*|C*|O(output-delimiter):d:sDn[!cbfF]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_CUT(NEWTOY(cut, "b*|c*|f*|F(regex-fields)*|C*|O(output-delimiter):d:sD(allow-duplicates)n[!cbfF]", TOYFLAG_USR|TOYFLAG_BIN))
 
 config CUT
   bool "cut"
@@ -25,7 +25,7 @@
     from start). By default selection ranges are sorted and collated, use -D
     to prevent that.
 
-    -b	Select bytes
+    -b	Select bytes (with -n round start/end down to start of utf8 char)
     -c	Select UTF-8 characters
     -C	Select unicode columns
     -d	Use DELIM (default is TAB for -f, run of whitespace for -F)
diff --git a/toys/posix/date.c b/toys/posix/date.c
index 99a4169..5a0f27e 100644
--- a/toys/posix/date.c
+++ b/toys/posix/date.c
@@ -7,7 +7,7 @@
  * Note: setting a 2 year date is 50 years back/forward from today,
  * not posix's hardwired magic dates.
 
-USE_DATE(NEWTOY(date, "d:D:I(iso)(iso-8601):;r:s:u(utc)[!dr]", TOYFLAG_BIN))
+USE_DATE(NEWTOY(date, "d:D:I(iso-8601):;r:s:u(utc)[!dr]", TOYFLAG_BIN))
 
 config DATE
   bool "date"
@@ -156,7 +156,7 @@
       struct tm tm = {};
       char *s = strptime(TT.d, TT.D+(*TT.D=='+'), &tm);
 
-      t = (s && *s) ? xvali_date(&tm, s) : xvali_date(0, TT.d);
+      t = (s && !*s) ? xvali_date(&tm, s) : xvali_date(0, TT.d);
     } else parse_date(TT.d, &t);
   } else {
     struct timespec ts;
diff --git a/toys/posix/df.c b/toys/posix/df.c
index caf8cf8..e07b33b 100644
--- a/toys/posix/df.c
+++ b/toys/posix/df.c
@@ -4,7 +4,7 @@
  *
  * See http://opengroup.org/onlinepubs/9699919799/utilities/df.html
 
-USE_DF(NEWTOY(df, "HPkhit*a[-HPh]", TOYFLAG_SBIN))
+USE_DF(NEWTOY(df, "HPkhit*a[-HPh]", TOYFLAG_BIN))
 
 config DF
   bool "df"
@@ -115,7 +115,7 @@
       suap[i] = (block*suap[i])/TT.units;
 
       if (FLAG(H)||FLAG(h))
-        human_readable(dsuapm[i+1], suap[i], FLAG(H) ? HR_1000 : 0);
+        human_readable(dsuapm[i+1], suap[i], HR_1000*FLAG(H));
       else sprintf(dsuapm[i+1], "%llu", suap[i]);
       dsuapm[i+2] = strchr(dsuapm[i+1], 0)+1;
     }
diff --git a/toys/posix/du.c b/toys/posix/du.c
index 8611867..8bf9575 100644
--- a/toys/posix/du.c
+++ b/toys/posix/du.c
@@ -89,17 +89,15 @@
   else if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) {
     struct inode_list {
       struct inode_list *next;
-      ino_t ino;
-      dev_t dev;
+      struct dev_ino di;
     } *new;
 
     for (new = *list; new; new = new->next)
-      if(new->ino == st->st_ino && new->dev == st->st_dev)
-        return 1;
+      if(same_dev_ino(st, &new->di)) return 1;
 
     new = xzalloc(sizeof(*new));
-    new->ino = st->st_ino;
-    new->dev = st->st_dev;
+    new->di.ino = st->st_ino;
+    new->di.dev = st->st_dev;
     new->next = *list;
     *list = new;
   }
@@ -116,16 +114,13 @@
   else if (!dirtree_notdotdot(node)) return 0;
 
   // detect swiching filesystems
-  if (FLAG(x) && (TT.st_dev != node->st.st_dev))
-    return 0;
+  if (FLAG(x) && TT.st_dev != node->st.st_dev) return 0;
 
   // Don't loop endlessly on recursive directory symlink
   if (FLAG(L)) {
     struct dirtree *try = node;
 
-    while ((try = try->parent))
-      if (node->st.st_dev==try->st.st_dev && node->st.st_ino==try->st.st_ino)
-        return 0;
+    while ((try = try->parent)) if (same_file(&node->st, &try->st)) return 0;
   }
 
   // Don't count hard links twice
@@ -136,7 +131,7 @@
   if (S_ISDIR(node->st.st_mode)) {
     if (!node->again) {
       TT.depth++;
-      return DIRTREE_COMEAGAIN|(DIRTREE_SYMFOLLOW*!!FLAG(L));
+      return DIRTREE_COMEAGAIN|DIRTREE_SYMFOLLOW*FLAG(L);
     } else TT.depth--;
   }
 
diff --git a/toys/posix/file.c b/toys/posix/file.c
index 2e65bcf..e48a547 100644
--- a/toys/posix/file.c
+++ b/toys/posix/file.c
@@ -4,7 +4,7 @@
  *
  * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/file.html
 
-USE_FILE(NEWTOY(file, "<1bhLs[!hL]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_FILE(NEWTOY(file, "<1b(brief)hLs[!hL]", TOYFLAG_USR|TOYFLAG_BIN))
 
 config FILE
   bool "file"
@@ -177,10 +177,10 @@
           goto bad;
         }
 
-        if (n_namesz==4 && !memcmp(note+12, "GNU", 4) && n_type==3) {
+        if (n_namesz==4 && !smemcmp(note+12, "GNU", 4) && n_type==3) {
           printf(", BuildID=");
           for (j = 0; j<n_descsz; j++) printf("%02x", note[16+j]);
-        } else if (n_namesz==8 && !memcmp(note+12, "Android", 8)) {
+        } else if (n_namesz==8 && !smemcmp(note+12, "Android", 8)) {
           if (n_type==1 /*.android.note.ident*/ && n_descsz >= 4) {
             printf(", for Android %d", (int)elf_int(note+20, 4));
             // NDK r14 and later also include NDK version info. OS binaries
@@ -206,6 +206,7 @@
 {
   char *s = toybuf;
   unsigned len, magic;
+  int ii;
 
   // zero through elf shnum, just in case
   memset(s, 0, 80);
@@ -215,6 +216,8 @@
   // 45 bytes: https://www.muppetlabs.com/~breadbox/software/tiny/teensy.html
   else if (len>=45 && strstart(&s, "\177ELF")) do_elf_file(fd);
   else if (strstart(&s, "!<arch>\n")) xputs("ar archive");
+  else if (*s=='%' && 2==sscanf(s, "%%PDF%d.%u", &ii, &magic))
+    xprintf("PDF document, version %d.%u\n", -ii, magic);
   else if (len>28 && strstart(&s, "\x89PNG\x0d\x0a\x1a\x0a")) {
     // PNG is big-endian: https://www.w3.org/TR/PNG/#7Integers-and-byte-order
     int chunk_length = peek_be(s, 4);
@@ -241,7 +244,7 @@
       s-3, (int)peek_le(s, 2), (int)peek_le(s+2, 2));
 
   // TODO: parsing JPEG for width/height is harder than GIF or PNG.
-  else if (len>32 && !memcmp(s, "\xff\xd8", 2)) xputs("JPEG image data");
+  else if (len>32 && !smemcmp(s, "\xff\xd8", 2)) xputs("JPEG image data");
 
   else if (len>8 && strstart(&s, "\xca\xfe\xba\xbe")) {
     unsigned count = peek_be(s, 4), i, arch;
@@ -255,9 +258,9 @@
         count, count == 1 ? "" : "s");
       for (i = 0, s += 4; i < count; i++, s += 20) {
         arch = peek_be(s, 4);
-	if (arch == 0x00000007) name = "i386";
+        if (arch == 0x00000007) name = "i386";
         else if (arch == 0x01000007) name = "x86_64";
-	else if (arch == 0x0000000c) name = "arm";
+        else if (arch == 0x0000000c) name = "arm";
         else if (arch == 0x0100000c) name = "arm64";
         else name = "unknown";
         xprintf(" [%s]", name);
@@ -304,7 +307,7 @@
   else if (len>31 && peek_be(s, 7) == 0xfd377a585a0000UL)
     xputs("xz compressed data");
   else if (len>10 && strstart(&s, "\x1f\x8b")) xputs("gzip compressed data");
-  else if (len>32 && !memcmp(s+1, "\xfa\xed\xfe", 3)) {
+  else if (len>32 && !smemcmp(s+1, "\xfa\xed\xfe", 3)) {
     int bit = (*s==0xce) ? 32 : 64;
     char *what = 0;
 
@@ -322,26 +325,26 @@
     else what = NULL;
     if (what) xprintf("%s\n", what);
     else xprintf("(bad type %d)\n", s[9]);
-  } else if (len>36 && !memcmp(s, "OggS\x00\x02", 6)) {
+  } else if (len>36 && !smemcmp(s, "OggS\x00\x02", 6)) {
     xprintf("Ogg data");
     // https://wiki.xiph.org/MIMETypesCodecs
-    if (!memcmp(s+28, "CELT    ", 8)) xprintf(", celt audio");
-    else if (!memcmp(s+28, "CMML    ", 8)) xprintf(", cmml text");
-    else if (!memcmp(s+28, "BBCD\0", 5)) xprintf(", dirac video");
-    else if (!memcmp(s+28, "\177FLAC", 5)) xprintf(", flac audio");
-    else if (!memcmp(s+28, "\x8bJNG\r\n\x1a\n", 8)) xprintf(", jng video");
-    else if (!memcmp(s+28, "\x80kate\0\0\0", 8)) xprintf(", kate text");
-    else if (!memcmp(s+28, "OggMIDI\0", 8)) xprintf(", midi text");
-    else if (!memcmp(s+28, "\x8aMNG\r\n\x1a\n", 8)) xprintf(", mng video");
-    else if (!memcmp(s+28, "OpusHead", 8)) xprintf(", opus audio");
-    else if (!memcmp(s+28, "PCM     ", 8)) xprintf(", pcm audio");
-    else if (!memcmp(s+28, "\x89PNG\r\n\x1a\n", 8)) xprintf(", png video");
-    else if (!memcmp(s+28, "Speex   ", 8)) xprintf(", speex audio");
-    else if (!memcmp(s+28, "\x80theora", 7)) xprintf(", theora video");
-    else if (!memcmp(s+28, "\x01vorbis", 7)) xprintf(", vorbis audio");
-    else if (!memcmp(s+28, "YUV4MPEG", 8)) xprintf(", yuv4mpeg video");
+    if (!smemcmp(s+28, "CELT    ", 8)) xprintf(", celt audio");
+    else if (!smemcmp(s+28, "CMML    ", 8)) xprintf(", cmml text");
+    else if (!smemcmp(s+28, "BBCD", 5)) xprintf(", dirac video");
+    else if (!smemcmp(s+28, "\177FLAC", 5)) xprintf(", flac audio");
+    else if (!smemcmp(s+28, "\x8bJNG\r\n\x1a\n", 8)) xprintf(", jng video");
+    else if (!smemcmp(s+28, "\x80kate\0\0", 8)) xprintf(", kate text");
+    else if (!smemcmp(s+28, "OggMIDI", 8)) xprintf(", midi text");
+    else if (!smemcmp(s+28, "\x8aMNG\r\n\x1a\n", 8)) xprintf(", mng video");
+    else if (!smemcmp(s+28, "OpusHead", 8)) xprintf(", opus audio");
+    else if (!smemcmp(s+28, "PCM     ", 8)) xprintf(", pcm audio");
+    else if (!smemcmp(s+28, "\x89PNG\r\n\x1a\n", 8)) xprintf(", png video");
+    else if (!smemcmp(s+28, "Speex   ", 8)) xprintf(", speex audio");
+    else if (!smemcmp(s+28, "\x80theora", 7)) xprintf(", theora video");
+    else if (!smemcmp(s+28, "\x01vorbis", 7)) xprintf(", vorbis audio");
+    else if (!smemcmp(s+28, "YUV4MPEG", 8)) xprintf(", yuv4mpeg video");
     xputc('\n');
-  } else if (len>32 && !memcmp(s, "RIF", 3) && !memcmp(s+8, "WAVEfmt ", 8)) {
+  } else if (len>32 && !smemcmp(s, "RIF", 3) && !smemcmp(s+8, "WAVEfmt ", 8)) {
     // https://en.wikipedia.org/wiki/WAV
     int le = (s[3] == 'F');
     int format = le ? peek_le(s+20, 2) : peek_be(s+20, 2);
@@ -369,7 +372,7 @@
     else xprintf("unknown format %d", format);
     xputc('\n');
   } else if (len>12 && peek_be(s, 4)==0x10000) xputs("TrueType font");
-  else if (len>12 && !memcmp(s, "ttcf\x00", 5)) {
+  else if (len>12 && !smemcmp(s, "ttcf", 5)) {
     xprintf("TrueType font collection, version %d, %d fonts\n",
             (int)peek_be(s+4, 2), (int)peek_be(s+8, 4));
 
@@ -379,8 +382,29 @@
   else if (strstart(&s,"-----BEGIN CERTIFICATE-----")) xputs("PEM certificate");
 
   // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680547(v=vs.85).aspx
-  else if (len>0x70 && !memcmp(s, "MZ", 2) &&
-      (magic=peek_le(s+0x3c,4))<len-4 && !memcmp(s+magic, "\x50\x45\0", 4)) {
+  else if (len>0x70 && !smemcmp(s, "MZ", 2) &&
+      (magic=peek_le(s+0x3c,4))<len-4 && !smemcmp(s+magic, "\x50\x45\0", 4)) {
+
+    // Linux kernel images look like PE files.
+    // https://www.kernel.org/doc/Documentation/arm64/booting.txt
+    // I've only ever seen LE, 4KiB pages, so ignore flags for now.
+    if (!smemcmp(s+0x38, "ARMd", 4)) return xputs("Linux arm64 kernel image");
+    else if (!smemcmp(s+0x202, "HdrS", 4)) {
+      // https://www.kernel.org/doc/Documentation/x86/boot.txt
+      unsigned ver_off = peek_le(s+0x20e, 2);
+
+      xprintf("Linux x86-64 kernel image");
+      if ((0x200 + ver_off) < len) {
+        s += 0x200 + ver_off;
+      } else {
+        if (lseek(fd, ver_off - len + 0x200, SEEK_CUR)<0 ||
+            (len = readall(fd, s, sizeof(toybuf)))<0)
+          return perror_msg("%s", name);
+      }
+      xprintf(", version %s\n", s);
+      return;
+    }
+
     xprintf("MS PE32%s executable %s", (peek_le(s+magic+24, 2)==0x20b)?"+":"",
         (peek_le(s+magic+22, 2)&0x2000)?"(DLL) ":"");
     if (peek_le(s+magic+20, 2)>70) {
@@ -394,7 +418,7 @@
     xprintf("x86%s\n", (peek_le(s+magic+4, 2)==0x14c) ? "" : "-64");
 
     // https://en.wikipedia.org/wiki/BMP_file_format
-  } else if (len>0x32 && !memcmp(s, "BM", 2) && !peek_be(s+6, 4)) {
+  } else if (len>0x32 && !smemcmp(s, "BM", 2) && !peek_be(s+6, 4)) {
     xprintf("BMP image, %d x %d, %d bpp\n", (int)peek_le(s+18, 4),
             (int)peek_le(s+22,4), (int)peek_le(s+28, 2));
 
@@ -408,7 +432,7 @@
         (int)peek_le(s+12, 4), (int)peek_le(s+20, 4));
 
     // https://android.googlesource.com/platform/system/tools/mkbootimg/+/refs/heads/master/include/bootimg/bootimg.h
-  } else if (len>1632 && !memcmp(s, "ANDROID!", 8)) {
+  } else if (len>1632 && !smemcmp(s, "ANDROID!", 8)) {
     xprintf("Android boot image v%d\n", (int)peek_le(s+40, 4));
 
     // https://source.android.com/devices/architecture/dto/partitions
@@ -417,7 +441,7 @@
             (int)peek_be(s+16, 4));
 
     // frameworks/base/core/java/com/android/internal/util/BinaryXmlSerializer.java
-  } else if (len>4 && !memcmp(s, "ABX", 3)) {
+  } else if (len>4 && !smemcmp(s, "ABX", 3)) {
     xprintf("Android Binary XML v%d\n", s[3]);
 
     // Text files, including shell scripts.
diff --git a/toys/posix/find.c b/toys/posix/find.c
index bca7c67..f82817c 100644
--- a/toys/posix/find.c
+++ b/toys/posix/find.c
@@ -29,19 +29,19 @@
     -group GROUP     belongs to group GROUP    -nogroup    group ID not known
     -perm  [-/]MODE  permissions (-=min /=any) -prune      ignore dir contents
     -size  N[c]      512 byte blocks (c=bytes) -xdev       only this filesystem
-    -links N         hardlink count            -atime N[u] accessed N units ago
-    -ctime N[u]      created N units ago       -mtime N[u] modified N units ago
-    -inum N          inode number N            -empty      empty files and dirs
-    -true            always true               -false      always false
-    -context PATTERN security context          -executable access(X_OK) perm+ACL
-    -samefile FILE   hardlink to FILE          -quit       exit immediately
-    -depth           ignore contents of dir    -maxdepth N at most N dirs down
-    -newer FILE      newer mtime than FILE     -mindepth N at least N dirs down
-    -newerXY FILE    X=acm time > FILE's Y=acm time (Y=t: FILE is literal time)
+    -links N         hardlink count            -empty      empty files and dirs
+    -atime N[u]      accessed N units ago      -true       always true
+    -ctime N[u]      created N units ago       -false      always false
+    -mtime N[u]      modified N units ago      -executable access(X_OK) perm+ACL
+    -inum  N         inode number N            -readable   access(R_OK) perm+ACL
+    -context PATTERN security context          -depth      contents before dir
+    -samefile FILE   hardlink to FILE          -maxdepth N at most N dirs down
+    -newer    FILE   newer mtime than FILE     -mindepth N at least N dirs down
+    -newerXY  FILE   X=acm time > FILE's Y=acm time (Y=t: FILE is literal time)
     -type [bcdflps]  type is (block, char, dir, file, symlink, pipe, socket)
 
-    Numbers N may be prefixed by a - (less than) or + (greater than). Units for
-    -Xtime are d (days, default), h (hours), m (minutes), or s (seconds).
+    Numbers N may be prefixed by - (less than) or + (greater than). Units for
+    -[acm]time are d (days, default), h (hours), m (minutes), or s (seconds).
 
     Combine matches with:
     !, -a, -o, ( )    not, and, or, group expressions
@@ -51,6 +51,7 @@
     -exec   Run command with path     -execdir       Run command in file's dir
     -ok     Ask before exec           -okdir         Ask before execdir
     -delete Remove matching file/dir  -printf FORMAT Print using format string
+    -quit   Exit immediately
 
     Commands substitute "{}" with matched file. End with ";" to run each file,
     or "+" (next argument after "{}") to collect and run with multiple files.
@@ -220,7 +221,7 @@
   // skip . and .. below topdir, handle -xdev and -depth
   if (new) {
     // Handle stat failures first.
-    if (new->again&2) {
+    if (new->again&DIRTREE_STATLESS) {
       if (!new->parent || errno != ENOENT) {
         perror_msg("'%s'", s = dirtree_path(new, 0));
         free(s);
@@ -238,7 +239,7 @@
         struct dirtree *n;
 
         for (n = new->parent; n; n = n->parent) {
-          if (n->st.st_ino==new->st.st_ino && n->st.st_dev==new->st.st_dev) {
+          if (same_file(&n->st, &new->st)) {
             error_msg("'%s': loop detected", s = dirtree_path(new, 0));
             free(s);
 
@@ -352,8 +353,9 @@
       if (check && bufgetgrgid(new->st.st_gid)) test = 0;
     } else if (!strcmp(s, "prune")) {
       if (check && S_ISDIR(new->st.st_mode) && !TT.depth) recurse = 0;
-    } else if (!strcmp(s, "executable")) {
-      if (check && faccessat(dirtree_parentfd(new), new->name,X_OK,0)) test = 0;
+    } else if (!strcmp(s, "executable") || !strcmp(s, "readable")) {
+      if (check && faccessat(dirtree_parentfd(new), new->name,
+          *s=='r' ? R_OK : X_OK, 0)) test = 0;
     } else if (!strcmp(s, "quit")) {
       if (check) {
         execdir(0, 1);
@@ -467,10 +469,7 @@
             uid_t uid;
             gid_t gid;
             struct timespec tm;
-            struct {
-              dev_t d;
-              ino_t i;
-            };
+            struct dev_ino di;
           };
         } *udl;
         struct stat st;
@@ -485,7 +484,7 @@
                 goto error;
               if (*s=='s' || !s[5] || s[6]!='t') {
                 xstat(arg, &st);
-                if (*s=='s') udl->d = st.st_dev, udl->i = st.st_ino;
+                if (*s=='s') udl->di.dev = st.st_dev, udl->di.ino = st.st_ino;
                 else udl->tm = *(struct timespec *)(((char *)&st)
                                + macoff[!s[5] ? 0 : stridx("ac", s[6])+1]);
               } else if (s[6] == 't') {
@@ -502,8 +501,7 @@
           if (check) {
             if (*s == 'u') test = new->st.st_uid == udl->uid;
             else if (*s == 'g') test = new->st.st_gid == udl->gid;
-            else if (*s == 's')
-              test = new->st.st_dev == udl->d && new->st.st_ino == udl->i;
+            else if (*s == 's') test = same_dev_ino(&new->st, &udl->di);
             else {
               struct timespec *tm = (void *)(((char *)&new->st)
                 + macoff[!s[5] ? 0 : stridx("ac", s[5])+1]);
@@ -621,7 +619,7 @@
             ff = 0;
             ch = *fmt;
 
-            // long long is its own stack size on LP64, so handle seperately
+            // long long is its own stack size on LP64, so handle separately
             if (ch == 'i' || ch == 's') {
               strcpy(next+len, "lld");
               printf(next, (ch == 'i') ? (long long)new->st.st_ino
diff --git a/toys/posix/grep.c b/toys/posix/grep.c
index 0474f7d..137c9c3 100644
--- a/toys/posix/grep.c
+++ b/toys/posix/grep.c
@@ -4,13 +4,10 @@
  *
  * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/grep.html
  *
- * Posix doesn't even specify -r, documenting deviations from it is silly.
-* echo hello | grep -w ''
-* echo '' | grep -w ''
-* echo hello | grep -f </dev/null
-*
+ * Posix doesn't even specify -r: too many deviations to document.
+ * TODO: -i is only ascii case insensitive, not unicode.
 
-USE_GREP(NEWTOY(grep, "(line-buffered)(color):;(exclude-dir)*S(exclude)*M(include)*ZzEFHIab(byte-offset)h(no-filename)ino(only-matching)rRsvwcL(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_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_EGREP(OLDTOY(egrep, grep, TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)|TOYFLAG_LINEBUF))
 USE_FGREP(OLDTOY(fgrep, grep, TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)|TOYFLAG_LINEBUF))
 
@@ -74,8 +71,8 @@
 
   char *purple, *cyan, *red, *green, *grey;
   struct double_list *reg;
-  char indelim, outdelim;
-  int found, tried;
+  int found, tried, delim;
+  struct arg_list *fixed[256];
 )
 
 struct reg {
@@ -96,16 +93,14 @@
 {
   if (!trim && FLAG(o)) return;
   if (name && FLAG(H)) printf("%s%s%s%c", TT.purple, name, TT.cyan, dash);
-  if (FLAG(c)) {
-    printf("%s%ld", TT.grey, lcount);
-    xputc(TT.outdelim);
-  } else if (lcount && FLAG(n)) numdash(lcount, dash);
+  if (FLAG(c)) xprintf("%s%ld%c", TT.grey, lcount, TT.delim);
+  else if (lcount && FLAG(n)) numdash(lcount, dash);
   if (bcount && FLAG(b)) numdash(bcount-1, dash);
   if (line) {
     if (FLAG(color)) xputsn(FLAG(o) ? TT.red : TT.grey);
     // support embedded NUL bytes in output
     xputsl(line, trim);
-    xputc(TT.outdelim);
+    xputc(TT.delim);
   }
 }
 
@@ -145,82 +140,84 @@
 
   // Loop through lines of input
   for (;;) {
-    char *line = 0, *start;
+    char *line = 0, *start, *ss, *pp;
     struct reg *shoe;
     size_t ulen;
     long len;
-    int matched = 0, rc = 1;
+    int matched = 0, rc = 1, move = 0, ii;
 
     // get next line, check and trim delimiter
     lcount++;
     errno = 0;
-    ulen = len = getdelim(&line, &ulen, TT.indelim, file);
+    ulen = len = getdelim(&line, &ulen, TT.delim, file);
     if (len == -1 && errno) perror_msg("%s", name);
     if (len<1) break;
-    if (line[ulen-1] == TT.indelim) line[--ulen] = 0;
+    if (line[ulen-1] == TT.delim) line[--ulen] = 0;
 
     // Prepare for next line
     start = line;
-    if (TT.reg) for (shoe = (void *)TT.reg; shoe; shoe = shoe->next)
-      shoe->rc = 0;
+    for (shoe = (void *)TT.reg; shoe; shoe = shoe->next) shoe->rc = 0;
 
     // Loop to handle multiple matches in same line
     do {
       regmatch_t *mm = (void *)toybuf;
+      struct arg_list *seek;
 
-      // Handle "fixed" (literal) matches
-      if (FLAG(F)) {
-        struct arg_list *seek, fseek;
-        char *s = 0;
+      mm->rm_so = mm->rm_eo = 0;
+      rc = 1;
 
-        for (seek = TT.e; seek; seek = seek->next) {
-          if (FLAG(x)) {
-            if (!(FLAG(i) ? strcasecmp : strcmp)(seek->arg, line)) s = line;
-          } else if (!*seek->arg) {
-            // No need to set fseek.next because this will match every line.
-            seek = &fseek;
-            fseek.arg = s = line;
-          } else if (FLAG(i)) s = strcasestr(start, seek->arg);
-          else s = strstr(start, seek->arg);
+      // Handle "fixed" (literal) matches (if any)
+      if (TT.e && *start) for (ss = start; ss-line<ulen; ss++) {
+        ii = FLAG(i) ? toupper(*ss) : *ss;
+        for (seek = TT.fixed[ii]; seek; seek = seek->next) {
+          if (*(pp = seek->arg)=='^' && !FLAG(F)) {
+            if (ss!=start) continue;
+            pp++;
+          }
+          for (ii = 0; pp[ii] && ss[ii]; ii++) {
+            if (!FLAG(F)) {
+              if (pp[ii]=='.') continue;
+              if (pp[ii]=='\\' && pp[ii+1]) pp++;
+              else if (pp[ii]=='$' && !pp[ii+1]) break;
+            }
+            if (FLAG(i)) {
+              if (toupper(pp[ii])!=toupper(ss[ii])) break;
+            } else if (pp[ii]!=ss[ii]) break;
+          }
+          if (pp[ii] && (pp[ii]!='$' || pp[ii+1] || ss[ii])) continue;
+          mm->rm_eo = (mm->rm_so = ss-start)+ii;
+          rc = 0;
 
-          if (s) break;
+          goto got;
+        }
+        if (FLAG(x)) break;
+      }
+
+      // Empty pattern always matches
+      if (rc && *TT.fixed && !FLAG(o)) rc = 0;
+got:
+      // Handle regex matches (if any)
+      for (shoe = (void *)TT.reg; shoe; shoe = shoe->next) {
+        // Do we need to re-check this regex?
+        if (!shoe->rc) {
+          shoe->m.rm_so -= move;
+          shoe->m.rm_eo -= move;
+          if (!matched || shoe->m.rm_so<0)
+            shoe->rc = regexec0(&shoe->r, start, ulen-(start-line), 1,
+                                &shoe->m, start==line ? 0 : REG_NOTBOL);
         }
 
-        if (s) {
+        // If we got a match, is it a _better_ match?
+        if (!shoe->rc && (rc || shoe->m.rm_so < mm->rm_so ||
+            (shoe->m.rm_so == mm->rm_so && shoe->m.rm_eo >= mm->rm_eo)))
+        {
+          mm = &shoe->m;
           rc = 0;
-          mm->rm_so = (s-start);
-          mm->rm_eo = (s-start)+strlen(seek->arg);
-        } else rc = 1;
-
-      // Handle regex matches
-      } else {
-        int baseline = mm->rm_eo;
-
-        mm->rm_so = mm->rm_eo = INT_MAX;
-        rc = 1;
-        for (shoe = (void *)TT.reg; shoe; shoe = shoe->next) {
-
-          // Do we need to re-check this regex?
-          if (!shoe->rc) {
-            shoe->m.rm_so -= baseline;
-            shoe->m.rm_eo -= baseline;
-            if (!matched || shoe->m.rm_so<0)
-              shoe->rc = regexec0(&shoe->r, start, ulen-(start-line), 1,
-                                  &shoe->m, start==line ? 0 : REG_NOTBOL);
-          }
-
-          // If we got a match, is it a _better_ match?
-          if (!shoe->rc && (shoe->m.rm_so < mm->rm_so ||
-              (shoe->m.rm_so == mm->rm_so && shoe->m.rm_eo >= mm->rm_eo)))
-          {
-            mm = &shoe->m;
-            rc = 0;
-          }
         }
       }
 
       if (!rc && FLAG(o) && !mm->rm_eo && ulen>start-line) {
-        start++;
+        move = 1;
         continue;
       }
 
@@ -238,7 +235,7 @@
           if (!isalnum(c) && c != '_') c = 0;
         }
         if (c) {
-          start += mm->rm_so+1;
+          move = mm->rm_so+1;
           continue;
         }
       }
@@ -247,7 +244,7 @@
         if (FLAG(o)) {
           if (rc) mm->rm_eo = ulen-(start-line);
           else if (!mm->rm_so) {
-            start += mm->rm_eo;
+            move = mm->rm_eo;
             continue;
           } else mm->rm_eo = mm->rm_so;
         } else {
@@ -271,7 +268,7 @@
         xexit();
       }
       if (FLAG(L) || FLAG(l)) {
-        if (FLAG(l)) xprintf("%s%c", name, TT.outdelim);
+        if (FLAG(l)) xprintf("%s%c", name, '\n'*!FLAG(Z));
         free(line);
         fclose(file);
         return;
@@ -308,9 +305,8 @@
         }
       }
 
-      start += mm->rm_eo;
-      if (mm->rm_so == mm->rm_eo) break;
-    } while (*start);
+      if (mm->rm_so == (move = mm->rm_eo)) break;
+    } while (*(start += move));
     offset += len;
 
     if (matched) {
@@ -318,7 +314,7 @@
       if (FLAG(color) && !FLAG(o)) {
         xputsn(TT.grey);
         if (ulen > start-line) xputsl(start, ulen-(start-line));
-        xputc(TT.outdelim);
+        xputc(TT.delim);
       }
       mcount++;
     } else {
@@ -355,7 +351,7 @@
     if (FLAG(m) && mcount >= TT.m) break;
   }
 
-  if (FLAG(L)) xprintf("%s%c", name, TT.outdelim);
+  if (FLAG(L)) xprintf("%s%c", name, TT.delim);
   else if (FLAG(c)) outline(0, ':', name, mcount, 0, 1);
 
   // loopfiles will also close the fd, but this frees an (opaque) struct.
@@ -368,21 +364,32 @@
   }
 }
 
+static int lensort(struct arg_list **a, struct arg_list **b)
+{
+  long la = strlen((*a)->arg), lb = strlen((*b)->arg);
+
+  if (la<lb) return -1;
+  if (la>lb) return 1;
+
+  return 0;
+}
+
 static void parse_regex(void)
 {
-  struct arg_list *al, *new, *list = NULL;
-  char *s, *ss;
+  struct arg_list *al, *new, *list = NULL, **last;
+  char *s, *ss, *special = "\\.^$[()|*+?{";
+  int len, ii, key;
 
   // Add all -f lines to -e list. (Yes, this is leaking allocation context for
   // exit to free. Not supporting nofork for this command any time soon.)
   al = TT.f ? TT.f : TT.e;
   while (al) {
     if (TT.f) {
-      if (!*(s = ss = xreadfile(al->arg, 0, 0))) {
-        free(ss);
+      if (!*(s = xreadfile(al->arg, 0, 0))) {
+        free(s);
         s = 0;
-      }
-    } else s = ss = al->arg;
+      } else if (*(ss = s+strlen(s)-1)=='\n') *ss = 0;
+    } else s = al->arg;
 
     // Advance, when we run out of -f switch to -e.
     al = al->next;
@@ -392,30 +399,69 @@
     }
     if (!s) continue;
 
+    // NOTE: even with -z, -f is still \n delimited. Blank line = match all
     // Split lines at \n, add individual lines to new list.
     do {
-      ss = FLAG(z) ? 0 : strchr(s, '\n');
-      if (ss) *(ss++) = 0;
+      if ((ss = strchr(s, '\n'))) *(ss++) = 0;
       new = xmalloc(sizeof(struct arg_list));
       new->next = list;
       new->arg = s;
       list = new;
       s = ss;
-    } while (ss && *s);
+    } while (s);
   }
   TT.e = list;
 
-  if (!FLAG(F)) {
-    // Convert regex list
-    for (al = TT.e; al; al = al->next) {
+  // Convert to regex where appropriate
+  for (last = &TT.e; *last;) {
+    // Can we use the fast path?
+    s = (*last)->arg;
+    if ('.'!=*s && !FLAG(F) && strcmp(s, "^$")) for (; *s; s++) {
+      if (*s=='\\') {
+        if (!s[1] || !strchr(special, *++s)) break;
+        if (!FLAG(E) && *s=='(') break;
+      } else if (*s>127 || strchr(special+4, *s)) break;
+    }
+
+    // Add entry to fast path (literal-ish match) or slow path (regexec)
+    if (!*s || FLAG(F)) last = &((*last)->next);
+    else {
       struct reg *shoe;
 
-      if (FLAG(o) && !*al->arg) continue;
       dlist_add_nomalloc(&TT.reg, (void *)(shoe = xmalloc(sizeof(struct reg))));
-      xregcomp(&shoe->r, al->arg,
-               (REG_EXTENDED*!!FLAG(E))|(REG_ICASE*!!FLAG(i)));
+      xregcomp(&shoe->r, (*last)->arg, REG_EXTENDED*FLAG(E)|REG_ICASE*FLAG(i));
+      al = *last;
+      *last = (*last)->next;
+      free(al);
     }
-    dlist_terminate(TT.reg);
+  }
+  dlist_terminate(TT.reg);
+
+  // Sort fast path patterns into buckets by first character
+  for (al = TT.e; al; al = new) {
+    new = al->next;
+    if (FLAG(F)) key = 0;
+    else {
+      key = '^'==*al->arg;
+      if ('\\'==al->arg[key]) key++;
+      else if ('$'==al->arg[key] && !al->arg[key+1]) key++;
+    }
+    key = al->arg[key];
+    if (FLAG(i)) key = toupper(key);
+    al->next = TT.fixed[key];
+    TT.fixed[key] = al;
+  }
+
+  // Sort each fast path pattern set by length so first hit is longest match
+  if (TT.e) for (key = 0; key<256; key++) {
+    if (!TT.fixed[key]) continue;
+    for (len = 0, al = TT.fixed[key]; al; al = al->next) len++;
+    last = xmalloc(len*sizeof(void *));
+    for (len = 0, al = TT.fixed[key]; al; al = al->next) last[len++] = al;
+    qsort(last, len, sizeof(void *), (void *)lensort);
+    for (ii = 0; ii<len; ii++) last[ii]->next = ii ? last[ii-1] : 0;
+    TT.fixed[key] = last[len-1];
+    free(last);
   }
 }
 
@@ -429,7 +475,7 @@
   if (S_ISDIR(new->st.st_mode)) {
     for (al = TT.exclude_dir; al; al = al->next)
       if (!fnmatch(al->arg, new->name, 0)) return 0;
-    return DIRTREE_RECURSE|(FLAG(R)?DIRTREE_SYMFOLLOW:0);
+    return DIRTREE_RECURSE|DIRTREE_SYMFOLLOW*FLAG(R);
   }
   if (TT.S || TT.M) {
     for (al = TT.S; al; al = al->next)
@@ -476,8 +522,7 @@
   if (!TT.A) TT.A = TT.C;
   if (!TT.B) TT.B = TT.C;
 
-  TT.indelim = '\n' * !FLAG(z);
-  TT.outdelim = '\n' * !FLAG(Z);
+  TT.delim = '\n' * !FLAG(z);
 
   // Handle egrep and fgrep
   if (*toys.which->name == 'e') toys.optflags |= FLAG_E;
diff --git a/toys/posix/head.c b/toys/posix/head.c
index d5c0700..04e1658 100644
--- a/toys/posix/head.c
+++ b/toys/posix/head.c
@@ -34,7 +34,7 @@
 
 static void do_head(int fd, char *name)
 {
-  long i, len, lines=TT.n, bytes=TT.c;
+  long i = 0, len = 0, lines = TT.n, bytes = TT.c;
 
   if ((toys.optc > 1 && !FLAG(q)) || FLAG(v)) {
     // Print an extra newline for all but the first file
@@ -50,11 +50,14 @@
     if (bytes) {
       i = bytes >= len ? len : bytes;
       bytes -= i;
-    } else for(i=0; i<len;) if (toybuf[i++] == '\n' && !--lines) break;
+    } else for(i = 0; i<len;) if (toybuf[i++] == '\n' && !--lines) break;
 
     xwrite(1, toybuf, i);
   }
 
+  // attempt to unget extra data
+  if (len>i) lseek(fd, i-len, SEEK_CUR);
+
   TT.file_no++;
 }
 
diff --git a/toys/posix/iconv.c b/toys/posix/iconv.c
index d272167..0674f3d 100644
--- a/toys/posix/iconv.c
+++ b/toys/posix/iconv.c
@@ -11,7 +11,6 @@
 config ICONV
   bool "iconv"
   default y
-  depends on TOYBOX_ICONV
   help
     usage: iconv [-f FROM] [-t TO] [FILE...]
 
diff --git a/toys/posix/kill.c b/toys/posix/kill.c
index 2eaba03..2f47f60 100644
--- a/toys/posix/kill.c
+++ b/toys/posix/kill.c
@@ -144,8 +144,9 @@
     while (*args) {
       char *arg = *(args++);
 
-      pid = strtol(arg, &tmp, 10);
-      if (*tmp || kill(pid, signum) < 0) error_msg("unknown pid '%s'", arg);
+      pid = estrtol(arg, &tmp, 10);
+      if (!errno && *tmp) errno = ESRCH;
+      if (errno || kill(pid, signum)<0) perror_msg("bad pid '%s'", arg);
     }
   }
 }
diff --git a/toys/posix/ln.c b/toys/posix/ln.c
index 3cd5c7b..65e1d46 100644
--- a/toys/posix/ln.c
+++ b/toys/posix/ln.c
@@ -52,13 +52,15 @@
   } else buf.st_mode = 0;
 
   for (i=0; i<toys.optc; i++) {
-    char *oldnew = 0, *try = toys.optargs[i];
+    char *oldnew = 0, *try = toys.optargs[i], *ss;
 
     if (S_ISDIR(buf.st_mode)) new = xmprintf("%s/%s", dest, basename(try));
     else new = dest;
 
     if (FLAG(r)) {
-      try = relative_path(new, try);
+      ss = xstrdup(new);
+      try = relative_path(dirname(ss), try, 1);
+      free(ss);
       if (!try) {
         if (new != dest) free(new);
         continue;
diff --git a/toys/posix/logger.c b/toys/posix/logger.c
index 906d64f..427a5f5 100644
--- a/toys/posix/logger.c
+++ b/toys/posix/logger.c
@@ -26,6 +26,8 @@
 
 GLOBALS(
   char *p, *t;
+
+  int priority;
 )
 
 // find str in names[], accepting unambiguous short matches
@@ -48,9 +50,15 @@
   return maybe;
 }
 
+static void syslog_line(char **pline, long len)
+{
+  if (!pline) return;
+  syslog(TT.priority, "%s", *pline);
+}
+
 void logger_main(void)
 {
-  int facility = LOG_USER, priority = LOG_NOTICE, len = 0;
+  int facility = LOG_USER, len = 0;
   char *s1, *s2, **arg,
     *priorities[] = {"emerg", "alert", "crit", "error", "warning", "notice",
                      "info", "debug"},
@@ -58,6 +66,7 @@
                      "lpr", "news", "uucp", "cron", "authpriv", "ftp"};
 
   if (!TT.t) TT.t = xgetpwuid(geteuid())->pw_name;
+  TT.priority = LOG_NOTICE;
   if (TT.p) {
     if (!(s1 = strchr(TT.p, '.'))) s1 = TT.p;
     else {
@@ -71,10 +80,11 @@
       facility *= 8;
     }
 
-    priority = arrayfind(s1, priorities, ARRAY_LEN(priorities));
-    if (priority<0) error_exit("bad priority: %s", s1);
+    TT.priority = arrayfind(s1, priorities, ARRAY_LEN(priorities));
+    if (TT.priority<0) error_exit("bad priority: %s", s1);
   }
 
+  openlog(TT.t, LOG_PERROR*FLAG(s), facility);
   if (toys.optc) {
     for (arg = toys.optargs; *arg; arg++) len += strlen(*arg)+1;
     s1 = s2 = xmalloc(len);
@@ -82,9 +92,7 @@
       if (arg != toys.optargs) *s2++ = ' ';
       s2 = stpcpy(s2, *arg);
     }
-  } else toybuf[readall(0, s1 = toybuf, sizeof(toybuf)-1)] = 0;
-
-  openlog(TT.t, LOG_PERROR*FLAG(s), facility);
-  syslog(priority, "%s", s1);
+    syslog(TT.priority, "%s", s1);
+  } else do_lines(0, '\n', syslog_line);
   closelog();
 }
diff --git a/toys/posix/ls.c b/toys/posix/ls.c
index 1551105..56d5c63 100644
--- a/toys/posix/ls.c
+++ b/toys/posix/ls.c
@@ -11,40 +11,45 @@
  *   add -Z -ll --color
  *   Posix says the -l date format should vary based on how recent it is
  *   and we do --time-style=long-iso instead
+ *   ignore -k because we default to 1024 byte blocks
 
-USE_LS(NEWTOY(ls, "(color):;(full-time)(show-control-chars)ZgoACFHLRSabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][!qb]", TOYFLAG_BIN|TOYFLAG_LOCALE))
+USE_LS(NEWTOY(ls, "(sort):(color):;(full-time)(show-control-chars)\241(group-directories-first)\376ZgoACFHLNRSUXabcdfhikl@mnpqrstuw#=80<0x1[-Cxm1][-Cxml][-Cxmo][-Cxmg][-cu][-ftS][-HL][-Nqb]", TOYFLAG_BIN|TOYFLAG_LOCALE))
 
 config LS
   bool "ls"
   default y
   help
-    usage: ls [-ACFHLRSZacdfhiklmnpqrstuwx1] [--color[=auto]] [FILE...]
+    usage: ls [-1ACFHLNRSUXZabcdfghilmnopqrstuwx] [--color[=auto]] [FILE...]
 
-    List files.
+    List files
 
     what to show:
-    -a  all files including .hidden    -b  escape nongraphic chars
-    -c  use ctime for timestamps       -d  directory, not contents
-    -i  inode number                   -p  put a '/' after dir names
-    -q  unprintable chars as '?'       -s  storage used (1024 byte units)
-    -u  use access time for timestamps -A  list all files but . and ..
-    -H  follow command line symlinks   -L  follow symlinks
-    -R  recursively list in subdirs    -F  append /dir *exe @sym |FIFO
+    -A  all files except . and ..      -a  all files including .hidden
+    -b  escape nongraphic chars        -d  directory, not contents
+    -F  append /dir *exe @sym |FIFO    -f  files (no sort/filter/format)
+    -H  follow command line symlinks   -i  inode number
+    -L  follow symlinks                -N  no escaping, even on tty
+    -p  put '/' after dir names        -q  unprintable chars as '?'
+    -R  recursively list in subdirs    -s  storage used (1024 byte units)
     -Z  security context
 
     output formats:
     -1  list one file per line         -C  columns (sorted vertically)
     -g  like -l but no owner           -h  human readable sizes
-    -l  long (show full details)       -m  comma separated
-    -n  like -l but numeric uid/gid    -o  like -l but no group
+    -l  long (show full details)       -ll long with nanoseconds (--full-time)
+    -m  comma separated                -n  long with numeric uid/gid
+    -o  long without group column      -r  reverse order
     -w  set column width               -x  columns (horizontal sort)
-    -ll long with nanoseconds (--full-time)
-    --color  device=yellow  symlink=turquoise/red  dir=blue  socket=purple
-             files: exe=green  suid=red  suidfile=redback  stickydir=greenback
-             =auto means detect if output is a tty.
 
-    sorting (default is alphabetical):
-    -f  unsorted    -r  reverse    -t  timestamp    -S  size
+    sort by:  (also --sort=longname,longname... ends with alphabetical)
+    -c  ctime      -r  reverse    -S  size     -t  time    -u  atime    -U  none
+    -X  extension  -!  dirfirst   -~  nocase
+
+    --color  =always (default)  =auto (when stdout is tty) =never
+        exe=green  suid=red  suidfile=redback  stickydir=greenback
+        device=yellow  symlink=turquoise/red  dir=blue  socket=purple
+
+    Long output uses -cu for display, use -ltc/-ltu to also sort by ctime/atime.
 */
 
 #define FOR_ls
@@ -55,9 +60,8 @@
 // ls -lR starts .: then ./subdir:
 
 GLOBALS(
-  long w;
-  long l;
-  char *color;
+  long w, l;
+  char *color, *sort;
 
   struct dirtree *files, *singledir;
   unsigned screen_width;
@@ -155,24 +159,86 @@
   len[7] = FLAG(Z) ? strwidth((char *)dt->extra) : 0;
 }
 
+// Perform one or more comparisons on a pair of files.
+// Reused FLAG_a to mean "alphabetical"
+static int do_compare(struct dirtree *a, struct dirtree *b, long flags)
+{
+  struct timespec *ts1 = 0, *ts2;
+  char *s1, *s2;
+  int ret;
+
+// TODO -? nocase  -! dirfirst
+
+  if (flags&FLAG_S) {
+    if (a->st.st_size > b->st.st_size) return -1;
+    else if (a->st.st_size < b->st.st_size) return 1;
+  }
+
+  if (flags&FLAG_t) ts1 = &a->st.st_mtim, ts2 = &b->st.st_mtim;
+  if (flags&FLAG_u) ts1 = &a->st.st_atim, ts2 = &b->st.st_atim;
+  if (flags&FLAG_c) ts1 = &a->st.st_ctim, ts2 = &b->st.st_ctim;
+  if (ts1) {
+    if (ts1->tv_sec > ts2->tv_sec) return -1;
+    else if (ts1->tv_sec < ts2->tv_sec) return 1;
+    else if (ts1->tv_nsec > ts2->tv_nsec) return -1;
+    else if (ts1->tv_nsec < ts2->tv_nsec) return 1;
+  }
+  if (flags&FLAG_X21) // dirfirst
+    if (S_ISDIR(a->st.st_mode)!=S_ISDIR(b->st.st_mode))
+      return S_ISDIR(a->st.st_mode) ? -1 : 1;
+
+  // -X is a form of alphabetical sort, without -~ do case sensitive comparison
+  if ((flags&FLAG_X) && (s1 = strrchr(a->name, '.')) && (s2 = strrchr(b->name, '.'))) {
+    if (!(flags&FLAG_X7E)) flags |= FLAG_a;
+  } else {
+    s1 = a->name;
+    s2 = b->name;
+  }
+
+  // case insensitive sort falls back to case sensitive sort when equal
+  ret = (flags&FLAG_X7E) ? strcasecmp(s1, s2) : 0;
+  if (!ret && (flags&FLAG_a)) ret = strcmp(s1, s2);
+
+  return ret;
+}
+
+int comma_start(char **aa, char *b)
+{
+  return strstart(aa, b) && (!**aa || **aa==',');
+}
+
+// callback for qsort
 static int compare(void *a, void *b)
 {
   struct dirtree *dta = *(struct dirtree **)a;
   struct dirtree *dtb = *(struct dirtree **)b;
-  int ret = 0, reverse = FLAG(r) ? -1 : 1;
+  char *ss = TT.sort;
+  long long ll = 0;
+  int ret = 0;
 
-  if (FLAG(S)) {
-    if (dta->st.st_size > dtb->st.st_size) ret = -1;
-    else if (dta->st.st_size < dtb->st.st_size) ret = 1;
+// TODO: test --sort=reverse with fallback alphabetical
+
+  if (ss) while (*ss) {
+    if (comma_start(&ss, "reverse")) toys.optflags |= FLAG_r;
+    else if (comma_start(&ss, "none")) goto skip;
+    else if (ret) continue;
+    else if (comma_start(&ss, "ctime")) ll = FLAG_c;
+    else if (comma_start(&ss, "size")) ll = FLAG_S;
+    else if (comma_start(&ss, "time")) ll = FLAG_t;
+    else if (comma_start(&ss, "atime")) ll = FLAG_u;
+    else if (comma_start(&ss, "nocase")) ll = FLAG_X7E;
+    else if (comma_start(&ss, "extension")) ll = FLAG_X;
+    else if (comma_start(&ss, "dirfirst")) ll = FLAG_X21;
+    else error_exit("bad --sort %s", ss);
+
+    ret = do_compare(dta, dtb, ll);
   }
-  if (FLAG(t)) {
-    if (dta->st.st_mtime > dtb->st.st_mtime) ret = -1;
-    else if (dta->st.st_mtime < dtb->st.st_mtime) ret = 1;
-    else if (dta->st.st_mtim.tv_nsec > dtb->st.st_mtim.tv_nsec) ret = -1;
-    else if (dta->st.st_mtim.tv_nsec < dtb->st.st_mtim.tv_nsec) ret = 1;
-  }
-  if (!ret) ret = strcmp(dta->name, dtb->name);
-  return ret * reverse;
+
+  if (!ret) ret = do_compare(dta, dtb, toys.optflags|FLAG_a);
+skip:
+  if (FLAG(r)) ret *= -1;
+
+  return ret;
 }
 
 // callback from dirtree_recurse() determining how to handle this entry.
@@ -203,7 +269,7 @@
   new->st.st_blocks >>= 1; // Use 1KiB blocks rather than 512B blocks.
 
   if (FLAG(a)||FLAG(f)) return DIRTREE_SAVE;
-  if (!FLAG(A) && new->name[0]=='.') return 0;
+  if (!FLAG(A) && *new->name=='.') return 0;
 
   return dirtree_notdotdot(new) & DIRTREE_SAVE;
 }
@@ -290,8 +356,8 @@
     if (toys.optflags == (FLAG_1|FLAG_f)) return;
   // Read directory contents. We dup() the fd because this will close it.
   // This reads/saves contents to display later, except for in "ls -1f" mode.
-  } else dirtree_recurse(indir, filter, dup(dirfd),
-      DIRTREE_STATLESS|DIRTREE_SYMFOLLOW*!!FLAG(L));
+  } else dirtree_recurse(indir, filter, dirfd,
+      DIRTREE_STATLESS|DIRTREE_SYMFOLLOW*FLAG(L));
 
   // Copy linked list to array and sort it. Directories go in array because
   // we visit them in sorted order too. (The nested loops let us measure and
@@ -315,7 +381,7 @@
   if (!FLAG(f)) {
     unsigned long long blocks = 0;
 
-    qsort(sort, dtlen, sizeof(void *), (void *)compare);
+    if (!FLAG(U)) qsort(sort, dtlen, sizeof(void *), (void *)compare);
     for (ul = 0; ul<dtlen; ul++) {
       entrylen(sort[ul], len);
       for (width = 0; width<8; width++)
@@ -379,9 +445,7 @@
     // Handle padding and wrapping for display purposes
     entrylen(dt, len);
     if (ul) {
-      int mm = !!FLAG(m);
-
-      if (mm) xputc(',');
+      if (FLAG(m)) xputc(',');
       if (FLAG(C)||FLAG(x)) {
         if (!curcol) xputc('\n');
         else {
@@ -392,8 +456,8 @@
         xputc('\n');
         width = 0;
       } else {
-        printf("  "+mm, 0); // shut up the stupid compiler
-        width += 2-mm;
+        xputsn("  "+FLAG(m));
+        width += 2-FLAG(m);
       }
     }
     width += *len;
@@ -518,6 +582,9 @@
     if (TT.color) toys.optflags ^= FLAG_color;
   }
 
+  // -N *doesn't* disable -q; you need --show-control-chars for that.
+  if (FLAG(N)) toys.optflags &= ~FLAG_b;
+
   TT.screen_width = 80;
   if (FLAG(w)) TT.screen_width = TT.w+2;
   else terminal_size(&TT.screen_width, NULL);
@@ -541,7 +608,7 @@
 
     // note: double_list->prev temporarily goes in dirtree->parent
     if (dt) {
-      if (dt->again&2) {
+      if (dt->again&DIRTREE_STATLESS) {
         perror_msg_raw(*s);
         free(dt);
       } else dlist_add_nomalloc((void *)&TT.files->child, (void *)dt);
diff --git a/toys/posix/nohup.c b/toys/posix/nohup.c
index 90d374e..48eb38c 100644
--- a/toys/posix/nohup.c
+++ b/toys/posix/nohup.c
@@ -21,17 +21,14 @@
 
 void nohup_main(void)
 {
-  toys.exitval = 125;
   xsignal(SIGHUP, SIG_IGN);
   if (isatty(1)) {
     close(1);
-    if (-1 == open("nohup.out", O_CREAT|O_APPEND|O_WRONLY,
-        S_IRUSR|S_IWUSR ))
-    {
+    if (open("nohup.out", O_CREAT|O_APPEND|O_WRONLY, 0600) == -1) {
       char *temp = getenv("HOME");
 
-      temp = xmprintf("%s/%s", temp ? temp : "", "nohup.out");
-      xcreate(temp, O_CREAT|O_APPEND|O_WRONLY, 0600);
+      xcreate(temp ? temp = xmprintf("%s/nohup.out", temp) : "nohup.out",
+        O_CREAT|O_APPEND|O_WRONLY, 0600);
       free(temp);
     }
   }
@@ -39,6 +36,6 @@
     close(0);
     xopen_stdio("/dev/null", O_RDONLY);
   }
-  toys.exitval = 0;
+
   xexec(toys.optargs);
 }
diff --git a/toys/posix/od.c b/toys/posix/od.c
index f0edcd7..c12055e 100644
--- a/toys/posix/od.c
+++ b/toys/posix/od.c
@@ -56,8 +56,8 @@
   // Handle ascii
   if (t->type < 2) {
     char c = TT.buf[(*offset)++];
-    pad += 4;
 
+    pad += 4;
     if (!t->type) {
       c &= 127;
       if (c<=32) sprintf(buf, "%.3s", ascii+(3*c));
@@ -93,8 +93,7 @@
   // Integer types
   } else {
     unsigned long long ll = 0, or;
-    char *c[] = {"%*lld", "%*llu", "%0*llo", "%0*llx"},
-      *class = c[t->type-2];
+    char *c[] = {"%*lld", "%*llu", "%0*llo", "%0*llx"}, *class = c[t->type-2];
 
     // Work out width of field
     if (t->size == 8) {
@@ -126,7 +125,6 @@
 
 static void od_outline(void)
 {
-  unsigned flags = toys.optflags;
   char buf[128], *abases[] = {"", "%07lld", "%07llo", "%06llx"};
   struct odtype *types = (struct odtype *)toybuf;
   int i, j, len, pad;
@@ -134,8 +132,8 @@
   if (TT.leftover<TT.w) memset(TT.buf+TT.leftover, 0, TT.w-TT.leftover);
 
   // Handle duplciate lines as *
-  if (!(flags&FLAG_v) && TT.j != TT.pos && TT.leftover
-    && !memcmp(TT.bufs[0], TT.bufs[1], TT.w))
+  if (!FLAG(v) && TT.j != TT.pos && TT.leftover
+    && !smemcmp(TT.bufs[0], TT.bufs[1], TT.w))
   {
     if (!TT.star) {
       xputs("*");
@@ -201,7 +199,7 @@
     char *buf = TT.buf + TT.leftover;
     int len = TT.w - TT.leftover;
 
-    if (toys.optflags & FLAG_N) {
+    if (FLAG(N)) {
       if (!TT.N) break;
       if (TT.N < len) len = TT.N;
     }
@@ -276,12 +274,12 @@
   // Collect -t entries
 
   for (arg = TT.t; arg; arg = arg->next) append_base(arg->arg);
-  if (toys.optflags & FLAG_b) append_base("o1");
-  if (toys.optflags & FLAG_c) append_base("c");
-  if (toys.optflags & FLAG_d) append_base("u2");
-  if (toys.optflags & FLAG_o) append_base("o2");
-  if (toys.optflags & FLAG_s) append_base("d2");
-  if (toys.optflags & FLAG_x) append_base("x2");
+  if (FLAG(b)) append_base("o1");
+  if (FLAG(c)) append_base("c");
+  if (FLAG(d)) append_base("u2");
+  if (FLAG(o)) append_base("o2");
+  if (FLAG(s)) append_base("d2");
+  if (FLAG(x)) append_base("x2");
   if (!TT.types) append_base("o2");
 
   loopfiles(toys.optargs, do_od);
diff --git a/toys/posix/patch.c b/toys/posix/patch.c
index 4b8c61c..6bdd461 100644
--- a/toys/posix/patch.c
+++ b/toys/posix/patch.c
@@ -143,7 +143,7 @@
 static int apply_one_hunk(void)
 {
   struct double_list *plist, *buf = 0, *check;
-  int matcheof, trail = 0, reverse = FLAG(R), backwarn = 0, allfuzz, fuzz, i;
+  int matcheof, trail = 0, backwarn = 0, allfuzz, fuzz, i;
   int (*lcmp)(char *aa, char *bb) = FLAG(l) ? (void *)loosecmp : (void *)strcmp;
 
   // Match EOF if there aren't as many ending context lines as beginning
@@ -157,7 +157,7 @@
     // Only allow fuzz if 2 context lines have multiple nonwhitespace chars.
     // avoids the "all context was blank or } lines" issue. Removed lines
     // count as context since they're matched.
-    if (c==' ' || c=="-+"[reverse]) {
+    if (c==' ' || c=="-+"[FLAG(R)]) {
       s = plist->data+1;
       while (isspace(*s)) s++;
       if (*s && s[1] && !isspace(s[1])) fuzz++;
@@ -167,7 +167,7 @@
   }
   matcheof = !trail || trail < TT.context;
   if (fuzz<2) allfuzz = 0;
-  else allfuzz = FLAG(F) ? TT.F : (TT.context ? TT.context-1 : 0);
+  else allfuzz = TT.F ? : TT.context ? TT.context-1 : 0;
 
   if (FLAG(x)) fprintf(stderr,"MATCHEOF=%c\n", matcheof ? 'Y' : 'N');
 
@@ -180,7 +180,7 @@
 
     // Figure out which line of hunk to compare with next. (Skip lines
     // of the hunk we'd be adding.)
-    while (plist && *plist->data == "+-"[reverse]) {
+    while (plist && *plist->data == "+-"[FLAG(R)]) {
       if (data && !lcmp(data, plist->data+1))
         if (!backwarn) backwarn = TT.linenum;
       plist = plist->next;
@@ -260,7 +260,7 @@
   }
 out:
   // We have a match.  Emit changed data.
-  TT.state = "-+"[reverse];
+  TT.state = "-+"[FLAG(R)];
   while ((plist = dlist_pop(&TT.current_hunk))) {
     if (TT.state == *plist->data || *plist->data == ' ') {
       if (*plist->data == ' ') dprintf(TT.fileout, "%s\n", buf->data);
@@ -279,13 +279,13 @@
 // read a filename that has been quoted or escaped
 static char *unquote_file(char *filename)
 {
-  char *s = filename, *t;
+  char *s = filename, *t, *newfile;
 
   // Return copy of file that wasn't quoted
   if (*s++ != '"' || !*s) return xstrdup(filename);
 
   // quoted and escaped filenames are larger than the original
-  for (t = filename = xmalloc(strlen(s) + 1); *s != '"'; s++) {
+  for (t = newfile = xmalloc(strlen(s) + 1); *s != '"'; s++) {
     if (!s[1]) error_exit("bad %s", filename);
 
     // don't accept escape sequences unless the filename is quoted
@@ -300,7 +300,7 @@
   }
   *t = 0;
 
-  return filename;
+  return newfile;
 }
 
 // Read a patch file and find hunks, opening/creating/deleting files.
@@ -313,7 +313,7 @@
 
 void patch_main(void)
 {
-  int reverse = FLAG(R), state = 0, patchlinenum = 0, strip = 0;
+  int state = 0, patchlinenum = 0, strip = 0;
   char *oldname = NULL, *newname = NULL;
 
   if (toys.optc == 2) TT.i = toys.optargs[1];
@@ -420,7 +420,7 @@
         // If an original file was provided on the command line, it overrides
         // *all* files mentioned in the patch, not just the first.
         if (toys.optc) {
-          char **which = reverse ? &oldname : &newname;
+          char **which = FLAG(R) ? &oldname : &newname;
 
           free(*which);
           *which = strdup(toys.optargs[0]);
@@ -429,12 +429,12 @@
           TT.p = 0;
         }
 
-        name = reverse ? oldname : newname;
+        name = FLAG(R) ? oldname : newname;
 
         // We're deleting oldname if new file is /dev/null (before -p)
         // or if new hunk is empty (zero context) after patching
-        if (!strcmp(name, "/dev/null") || !(reverse ? oldsum : newsum)) {
-          name = reverse ? newname : oldname;
+        if (!strcmp(name, "/dev/null") || !(FLAG(R) ? oldsum : newsum)) {
+          name = FLAG(R) ? newname : oldname;
           del++;
         }
 
@@ -449,7 +449,7 @@
 
         if (del) {
           if (!FLAG(s)) printf("removing %s\n", name);
-          xunlink(name);
+          if (!FLAG(dry_run)) xunlink(name);
           state = 0;
         // If we've got a file to open, do so.
         } else if (!FLAG(p) || i <= TT.p) {
@@ -457,8 +457,11 @@
           if ((!strcmp(oldname, "/dev/null") || !oldsum) && access(name, F_OK))
           {
             if (!FLAG(s)) printf("creating %s\n", name);
-            if (mkpath(name)) perror_exit("mkpath %s", name);
-            TT.filein = xcreate(name, O_CREAT|O_EXCL|O_RDWR, 0666);
+            if (FLAG(dry_run)) TT.filein = xopen("/dev/null", O_RDWR);
+            else {
+              if (mkpath(name)) perror_exit("mkpath %s", name);
+              TT.filein = xcreate(name, O_CREAT|O_EXCL|O_RDWR, 0666);
+            }
           } else {
             if (!FLAG(s)) printf("patching %s\n", name);
             TT.filein = xopenro(name);
diff --git a/toys/posix/printf.c b/toys/posix/printf.c
index 2cbf303..9337473 100644
--- a/toys/posix/printf.c
+++ b/toys/posix/printf.c
@@ -5,7 +5,7 @@
  *
  * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html
  *
- * todo: *m$ ala printf("%1$d:%2$.*3$d:%4$.*3$d\n", hour, min, precision, sec);
+ * TODO: *m$ ala printf("%1$d:%2$.*3$d:%4$.*3$d\n", hour, min, precision, sec);
 
 USE_PRINTF(NEWTOY(printf, "<1?^", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_MAYFORK))
 
@@ -23,7 +23,7 @@
 #include "toys.h"
 
 // Detect matching character (return true/false) and advance pointer if match.
-static int eat(char **s, char c)
+static int chrstart(char **s, char c)
 {
   int x = (**s == c);
 
@@ -42,7 +42,7 @@
   if (*ptr == 'c') xexit();
 
   // 0x12 hex escapes have 1-2 digits, \123 octal escapes have 1-3 digits.
-  if (eat(&ptr, 'x')) base = 16;
+  if (chrstart(&ptr, 'x')) base = 16;
   else {
     if (posix && *ptr=='0') ptr++;
     if (*ptr >= '0' && *ptr <= '7') base = 8;
@@ -85,8 +85,8 @@
 
     // Loop through characters in format
     while (*f) {
-      if (eat(&f, '\\')) putchar(handle_slash(&f, 0));
-      else if (!eat(&f, '%') || *f == '%') putchar(*f++);
+      if (chrstart(&f, '\\')) putchar(handle_slash(&f, 0));
+      else if (!chrstart(&f, '%') || *f == '%') putchar(*f++);
 
       // Handle %escape
       else {
@@ -97,10 +97,10 @@
         *to++ = '%';
         while (strchr("-+# '0", *f) && (to-toybuf)<10) *to++ = *f++;
         for (;;) {
-          if (eat(&f, '*')) {
+          if (chrstart(&f, '*')) {
             if (*arg) wp[i] = atolx(*arg++);
           } else while (*f >= '0' && *f <= '9') wp[i] = (wp[i]*10)+(*f++)-'0';
-          if (i++ || !eat(&f, '.')) break;
+          if (i++ || !chrstart(&f, '.')) break;
           wp[1] = 0;
         }
         c = *f++;
@@ -110,7 +110,8 @@
 
         // Output %esc using parsed format string
         if (c == 'b') {
-          while (*aa) putchar(eat(&aa, '\\') ? handle_slash(&aa, 1) : *aa++);
+          while (*aa)
+            putchar(chrstart(&aa, '\\') ? handle_slash(&aa, 1) : *aa++);
 
           continue;
         } else if (c == 'c') printf(toybuf, wp[0], wp[1], *aa);
@@ -130,7 +131,7 @@
           printf(toybuf, wp[0], wp[1], ld);
         } else error_exit("bad %%%c@%ld", c, (long)(f-*toys.optargs));
 
-        if (end && (errno || *end)) perror_msg("bad %%%c %s", c, aa);
+        if (end && (*end || errno==ERANGE)) perror_msg("bad %%%c %s", c, aa);
       }
     }
 
diff --git a/toys/posix/ps.c b/toys/posix/ps.c
index 3884097..2ff3ba7 100644
--- a/toys/posix/ps.c
+++ b/toys/posix/ps.c
@@ -209,7 +209,10 @@
     } pgrep;
   };
 
-  struct ptr_len gg, GG, pp, PP, ss, tt, uu, UU;
+  struct ps_ptr_len {
+    void *ptr;
+    long len;
+  } gg, GG, pp, PP, ss, tt, uu, UU;
   struct dirtree *threadparent;
   unsigned width, height, scroll;
   dev_t tty;
@@ -461,7 +464,7 @@
 // process match filter for top/ps/pgrep: Return 0 to discard, nonzero to keep
 static int shared_match_process(long long *slot)
 {
-  struct ptr_len match[] = {
+  struct ps_ptr_len match[] = {
     {&TT.gg, SLOT_gid}, {&TT.GG, SLOT_rgid}, {&TT.pp, SLOT_pid},
     {&TT.PP, SLOT_ppid}, {&TT.ss, SLOT_sid}, {&TT.tt, SLOT_ttynr},
     {&TT.uu, SLOT_uid}, {&TT.UU, SLOT_ruid}
@@ -471,7 +474,7 @@
 
   // Do we have -g -G -p -P -s -t -u -U options selecting processes?
   for (i = 0; i < ARRAY_LEN(match); i++) {
-    struct ptr_len *mm = match[i].ptr;
+    struct ps_ptr_len *mm = match[i].ptr;
 
     if (mm->len) {
       ll = mm->ptr;
@@ -842,7 +845,7 @@
     off_t temp = 6;
 
     sprintf(buf, "%lld/exe", slot[SLOT_tid]);
-    if (readfileat(fd, buf, buf, &temp) && !memcmp(buf, "\177ELF", 4)) {
+    if (readfileat(fd, buf, buf, &temp) && !smemcmp(buf, "\177ELF", 4)) {
       if (buf[4] == 1) slot[SLOT_bits] = 32;
       else if (buf[4] == 2) slot[SLOT_bits] = 64;
     }
@@ -1146,7 +1149,7 @@
 // Parse command line options -p -s -t -u -U -g -G
 static char *parse_rest(void *data, char *str, int len)
 {
-  struct ptr_len *pl = (struct ptr_len *)data;
+  struct ps_ptr_len *pl = (struct ps_ptr_len *)data;
   long *ll = pl->ptr;
   char *end;
   int num = 0;
@@ -1345,7 +1348,7 @@
     not_o = "F,S,UID,%sPPID,C,PRI,NI,BIT,SZ,WCHAN,TTY,TIME,CMD";
   else if (CFG_TOYBOX_ON_ANDROID)
     sprintf(not_o = toybuf+128,
-            "USER,%%sPPID,VSIZE,RSS,WCHAN:10,ADDR:10,S,%s",
+            "USER,%%sPPID,VSIZE:10,RSS,WCHAN:10,ADDR:10,S,%s",
             FLAG(T) ? "CMD" : "NAME");
   sprintf(toybuf, not_o, FLAG(T) ? "PID,TID," : "PID,");
 
@@ -1518,13 +1521,13 @@
     "iow", "irq", "sirq", "host"};
   unsigned tock = 0;
   int i, lines, topoff = 0, done = 0;
-  char stdout_buf[BUFSIZ];
+  char stdout_buf[8192];
 
   if (!TT.fields) perror_exit("no -o");
 
   // Avoid flicker and hide the cursor in interactive mode.
   if (!FLAG(b)) {
-    setbuf(stdout, stdout_buf);
+    setbuffer(stdout, stdout_buf, sizeof(stdout_buf));
     sigatexit(top_cursor_cleanup);
     xputsn("\e[?25l");
   }
@@ -1631,8 +1634,8 @@
             run[1+stridx("RTtZ", *string_field(mix.tb[i], &field))]++;
           sprintf(toybuf,
             "%ss: %d total, %3ld running, %3ld sleeping, %3ld stopped, "
-            "%3ld zombie", FLAG(H)?"Thread":"Task", mix.count, run[1], run[0],
-            run[2]+run[3], run[4]);
+            "%3ld zombie", FLAG(H) ? "Thread" : "Task", mix.count, run[1],
+            run[0], run[2]+run[3], run[4]);
           lines = header_line(lines, 0);
 
           if (readfile("/proc/meminfo", toybuf+256, sizeof(toybuf)-256)) {
@@ -1840,12 +1843,12 @@
   if (!FLAG(a)) merge_deltas(oslot, nslot, milis);
   else oslot[SLOT_upticks] = ((millitime()-TT.time)*TT.ticks)/1000;
 
-  return !FLAG(O)||oslot[SLOT_iobytes+!FLAG(A)];
+  return !FLAG(O) || oslot[SLOT_iobytes+!FLAG(A)];
 }
 
 void iotop_main(void)
 {
-  char *s1 = 0, *s2 = 0, *d = "D"+!!FLAG(A);
+  char *s1 = 0, *s2 = 0, *d = "D"+FLAG(A);
 
   if (FLAG(K)) TT.forcek++;
 
@@ -1880,9 +1883,7 @@
   }
   if (!FLAG(c) && (!TT.pgrep.signal || TT.tty)) {
     printf("%lld", *tb->slot);
-    if (FLAG(l))
-      printf(" %s", tb->str+tb->offset[4]*!!FLAG(f));
-    
+    if (FLAG(l)) printf(" %s", tb->str+tb->offset[4]*FLAG(f));
     printf("%s", TT.pgrep.d ? TT.pgrep.d : "\n");
   }
 }
@@ -1892,7 +1893,7 @@
   struct procpid *tb = p;
   regmatch_t match;
   struct regex_list *reg;
-  char *name = tb->str+tb->offset[4]*!!FLAG(f);
+  char *name = tb->str+tb->offset[4]*FLAG(f);
 
   // Never match ourselves.
   if (TT.pgrep.self == *tb->slot) return;
diff --git a/toys/posix/pwd.c b/toys/posix/pwd.c
index c7dc78f..c6f45ad 100644
--- a/toys/posix/pwd.c
+++ b/toys/posix/pwd.c
@@ -41,8 +41,7 @@
 
     // If current directory exists, make sure it matches.
     if (s && pwd)
-        if (stat(pwd, &st1) || stat(PWD, &st2) || st1.st_ino != st2.st_ino ||
-            st1.st_dev != st2.st_dev) s = 0;
+      if (stat(pwd, &st1) || stat(PWD, &st2) || !same_file(&st1, &st2)) s = 0;
   } else s = 0;
 
   // If -L didn't give us a valid path, use cwd.
diff --git a/toys/posix/rm.c b/toys/posix/rm.c
index be611e6..cfe282f 100644
--- a/toys/posix/rm.c
+++ b/toys/posix/rm.c
@@ -4,7 +4,7 @@
  *
  * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/rm.html
 
-USE_RM(NEWTOY(rm, "fiRrv[-fi]", TOYFLAG_BIN))
+USE_RM(NEWTOY(rm, "f(force)iRrv[-fi]", TOYFLAG_BIN))
 
 config RM
   bool "rm"
diff --git a/toys/posix/sed.c b/toys/posix/sed.c
index cea12ea..0de9063 100644
--- a/toys/posix/sed.c
+++ b/toys/posix/sed.c
@@ -4,6 +4,8 @@
  *
  * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sed.html
  *
+ * xform See https://www.gnu.org/software/tar/manual/html_section/transform.html
+ *
  * TODO: lines > 2G could wrap signed int length counters. Not just getline()
  * but N and s///
  * TODO: make y// handle unicode, unicode delimiters
@@ -12,12 +14,15 @@
  * test '//q' with no previous regex, also repeat previous regex?
  *
  * Deviations from POSIX: allow extended regular expressions with -r,
- * editing in place with -i, separate with -s, NUL-separated input with -z,
+ * editing in place with -i, separate with -s, NUL-delimited strings with -z,
  * printf escapes in text, line continuations, semicolons after all commands,
  * 2-address anywhere an address is allowed, "T" command, multiline
  * continuations for [abc], \; to end [abc] argument before end of line.
+ * Explicit violations of stuff posix says NOT to do: N at EOF does default
+ * print, l escapes \n
+ * Added --tarxform mode to support tar --xform
 
-USE_SED(NEWTOY(sed, "(help)(version)e*f*i:;nErz(null-data)s[+Er]", TOYFLAG_BIN|TOYFLAG_LOCALE|TOYFLAG_NOHELP))
+USE_SED(NEWTOY(sed, "(help)(version)(tarxform)e*f*i:;nErz(null-data)s[+Er]", TOYFLAG_BIN|TOYFLAG_LOCALE|TOYFLAG_NOHELP))
 
 config SED
   bool "sed"
@@ -74,8 +79,8 @@
       G  Get remembered line (appending to current line)
       h  Remember this line (overwriting remembered line)
       H  Remember this line (appending to remembered line, if any)
-      l  Print line escaping \abfrtv (but not \n), octal escape other nonprintng
-         chars, wrap lines to terminal width with \, append $ to end of line.
+      l  Print line escaping \abfrtvn, octal escape other nonprintng chars,
+         wrap lines to terminal width with \, append $ to end of line.
       n  Print default output and read next line over current line (quit at EOF)
       N  Append \n and next line of input to this line. Quit at EOF without
          default output. Advances line counter for ADDRESS and "=".
@@ -126,12 +131,12 @@
   // processed pattern list
   struct double_list *pattern;
 
-  char *nextline, *remember;
+  char *nextline, *remember, *tarxform;
   void *restart, *lastregex;
   long nextlen, rememberlen, count;
   int fdout, noeol;
-  unsigned xx;
-  char delim;
+  unsigned xx, tarxlen, xflags;
+  char delim, xftype;
 )
 
 // Linked list of parsed sed commands. Offset fields indicate location where
@@ -147,21 +152,38 @@
   int rmatch[2];  // offset of regex struct for prefix matches (/abc/,/def/p)
   int arg1, arg2, w; // offset of two arguments per command, plus s//w filename
   unsigned not, hit;
-  unsigned sflags; // s///flag bits: i=1, g=2, p=4, x=8
+  unsigned sflags; // s///flag bits, see SFLAG macros below
   char c; // action
 };
 
+#define SFLAG_i 1
+#define SFLAG_g 2
+#define SFLAG_p 4
+#define SFLAG_x 8
+#define SFLAG_slash 16
+#define SFLAG_R 32
+#define SFLAG_S 64
+#define SFLAG_H 128
+
 // Write out line with potential embedded NUL, handling eol/noeol
 static int emit(char *line, long len, int eol)
 {
-  int l, old = line[len];
+  int l = len, old = line[len];
 
-  if (TT.noeol && !writeall(TT.fdout, "\n", 1)) return 1;
+  if (FLAG(tarxform)) {
+    TT.tarxform = xrealloc(TT.tarxform, TT.tarxlen+len+TT.noeol+eol);
+    if (TT.noeol) TT.tarxform[TT.tarxlen++] = TT.delim;
+    memcpy(TT.tarxform+TT.tarxlen, line, len);
+    TT.tarxlen += len;
+    if (eol) TT.tarxform[TT.tarxlen++] = TT.delim;
+  } else {
+    if (TT.noeol && !writeall(TT.fdout, &TT.delim, 1)) return 1;
+    if (eol) line[len++] = TT.delim;
+    if (!len) return 0;
+    l = writeall(TT.fdout, line, len);
+    if (eol) line[len-1] = old;
+  }
   TT.noeol = !eol;
-  if (eol) line[len++] = '\n';
-  if (!len) return 0;
-  l = writeall(TT.fdout, line, len);
-  if (eol) line[len-1] = old;
   if (l != len) {
     if (TT.fdout != 1) perror_msg("short write");
 
@@ -180,7 +202,7 @@
 
   if (newline) newlen = -newlen;
   s = *old = xrealloc(*old, oldlen+newlen+newline+1);
-  if (newline) s[oldlen++] = '\n';
+  if (newline) s[oldlen++] = TT.delim;
   memcpy(s+oldlen, new, newlen);
   s[oldlen+newlen] = 0;
 
@@ -206,32 +228,52 @@
     int file;
     char *str;
   } *append = 0;
-  char *line = TT.nextline;
-  long len = TT.nextlen;
+  char *line;
+  long len;
   struct sedcmd *command;
   int eol = 0, tea = 0;
 
-  // Ignore EOF for all files before last unless -i
-  if (!pline && !FLAG(i) && !FLAG(s)) return;
+  if (FLAG(tarxform)) {
+    if (!pline) return;
 
-  // Grab next line for deferred processing (EOF detection: we get a NULL
-  // pline at EOF to flush last line). Note that only end of _last_ input
-  // file matches $ (unless we're doing -i).
-  TT.nextline = 0;
-  TT.nextlen = 0;
-  if (pline) {
-    TT.nextline = *pline;
-    TT.nextlen = plen;
+    line = *pline;
+    len = plen;
     *pline = 0;
+    pline = 0;
+  } else {
+    line = TT.nextline;
+    len = TT.nextlen;
+
+    // Ignore EOF for all files before last unless -i or -s
+    if (!pline && !FLAG(i) && !FLAG(s)) return;
+
+    // Grab next line for deferred processing (EOF detection: we get a NULL
+    // pline at EOF to flush last line). Note that only end of _last_ input
+    // file matches $ (unless we're doing -i).
+    TT.nextline = 0;
+    TT.nextlen = 0;
+    if (pline) {
+      TT.nextline = *pline;
+      TT.nextlen = plen;
+      *pline = 0;
+    }
   }
 
   if (!line || !len) return;
-  if (line[len-1] == '\n') line[--len] = eol++;
+  if (line[len-1] == TT.delim) line[--len] = eol++;
+  if (FLAG(tarxform) && len) {
+    TT.xftype = line[--len];
+    line[len] = 0;
+  }
   TT.count++;
 
-  // The restart-1 is because we added one to make sure it wasn't NULL,
-  // otherwise N as last command would restart script
-  command = TT.restart ? ((struct sedcmd *)TT.restart)-1 : (void *)TT.pattern;
+  // To prevent N as last command from restarting script, we added 1 to restart
+  // so we'd use it here even when NULL. Alas, compilers that think C has
+  // references instead of pointers assume ptr-1 can never be NULL (demonstrably
+  // untrue) and inappropriately dead code eliminate, so use LP64 math until
+  // we get a -fpointers-are-not-references compiler option.
+  command = (void *)(TT.restart ? ((unsigned long)TT.restart)-1
+    : (unsigned long)TT.pattern);
   TT.restart = 0;
 
   while (command) {
@@ -328,7 +370,7 @@
     } else if (c=='D') {
       // Delete up to \n or end of buffer
       str = line;
-      while ((str-line)<len) if (*(str++) == '\n') break;
+      while ((str-line)<len) if (*(str++) == TT.delim) break;
       len -= str - line;
       memmove(line, str, len);
 
@@ -344,11 +386,11 @@
       continue;
     } else if (c=='g') {
       free(line);
-      line = xstrdup(TT.remember);
+      line = xmemdup(TT.remember, TT.rememberlen+1);
       len = TT.rememberlen;
     } else if (c=='G') {
       line = xrealloc(line, len+TT.rememberlen+2);
-      line[len++] = '\n';
+      line[len++] = TT.delim;
       memcpy(line+len, TT.remember, TT.rememberlen);
       line[len += TT.rememberlen] = 0;
     } else if (c=='h') {
@@ -357,7 +399,7 @@
       TT.rememberlen = len;
     } else if (c=='H') {
       TT.remember = xrealloc(TT.remember, TT.rememberlen+len+2);
-      TT.remember[TT.rememberlen++] = '\n';
+      TT.remember[TT.rememberlen++] = TT.delim;
       memcpy(TT.remember+TT.rememberlen, line, len);
       TT.remember[TT.rememberlen += len] = 0;
     } else if (c=='i') {
@@ -379,24 +421,26 @@
           emit(toybuf, off, 1);
           off = 0;
         }
-        x = stridx("\\\a\b\f\r\t\v", line[i]);
+        x = stridx("\\\a\b\f\r\t\v\n", line[i]);
         if (x != -1) {
           toybuf[off++] = '\\';
-          toybuf[off++] = "\\abfrtv"[x];
+          toybuf[off++] = "\\abfrtvn"[x];
         } else if (line[i] >= ' ') toybuf[off++] = line[i];
         else off += sprintf(toybuf+off, "\\%03o", line[i]);
       }
       toybuf[off++] = '$';
       emit(toybuf, off, 1);
     } else if (c=='n') {
-      TT.restart = command->next+1;
+      // The +1 forces restart processing even when next is null
+      TT.restart = (void *)(((unsigned long)command->next)+1);
 
       break;
     } else if (c=='N') {
       // Can't just grab next line because we could have multiple N and
       // we need to actually read ahead to get N;$p EOF detection right.
       if (pline) {
-        TT.restart = command->next+1;
+        // The +1 forces restart processing even when  next is null
+        TT.restart = (void *)(((unsigned long)command->next)+1);
         extend_string(&line, TT.nextline, len, -TT.nextlen);
         free(TT.nextline);
         TT.nextline = line;
@@ -407,7 +451,7 @@
       // Pending append goes out right after N
       goto done; 
     } else if (c=='p' || c=='P') {
-      char *l = (c=='P') ? strchr(line, '\n') : 0;
+      char *l = (c=='P') ? strchr(line, TT.delim) : 0;
 
       if (emit(line, l ? l-line : len, eol)) break;
     } else if (c=='q' || c=='Q') {
@@ -425,23 +469,33 @@
       regmatch_t *match = (void *)toybuf;
       regex_t *reg = get_regex(command, command->arg1);
       int mflags = 0, count = 0, l2used = 0, zmatch = 1, l2l = len, l2old = 0,
-        mlen, off, newlen;
+        bonk = 0, mlen, off, newlen;
+
+      // Skip suppressed --tarxform types
+      if (TT.xftype && (command->sflags & (SFLAG_R<<stridx("rsh", TT.xftype))));
 
       // Loop finding match in remaining line (up to remaining len)
-      while (!regexec0(reg, rline, len-(rline-line), 10, match, mflags)) {
+      else while (!regexec0(reg, rline, len-(rline-line), 10, match, mflags)) {
+        mlen = match[0].rm_eo-match[0].rm_so;
+
+        // xform matches ending in / aren't allowed to match entire line
+        if ((command->sflags & SFLAG_slash) && mlen==len) {
+          while (len && ++bonk && line[--len]=='/');
+          continue;
+        }
+
         mflags = REG_NOTBOL;
 
         // Zero length matches don't count immediately after a previous match
-        mlen = match[0].rm_eo-match[0].rm_so;
         if (!mlen && !zmatch) {
           if (rline-line == len) break;
-          l2[l2used++] = *rline++;
+          if (l2) l2[l2used++] = *rline++;
           zmatch++;
           continue;
         } else zmatch = 0;
 
         // If we're replacing only a specific match, skip if this isn't it
-        off = command->sflags>>4;
+        off = command->sflags>>8;
         if (off && off != ++count) {
           if (l2) memcpy(l2+l2used, rline, match[0].rm_eo);
           l2used += match[0].rm_eo;
@@ -470,7 +524,11 @@
 
         // Adjust allocation size of new string, copy data we know we'll keep
         l2l += newlen-mlen;
-        if ((l2l|0xfff) > l2old) l2 = xrealloc(l2, l2old = (l2l|0xfff)+1);
+        if ((mlen = l2l|0xfff) > l2old) {
+          l2 = xrealloc(l2, ++mlen);
+          if (l2used && !l2old) memcpy(l2, rline-l2used, l2used);
+          l2old = mlen;
+        }
         if (match[0].rm_so) {
           memcpy(l2+l2used, rline, match[0].rm_so);
           l2used += match[0].rm_so;
@@ -503,9 +561,9 @@
         l2used += newlen;
         rline += match[0].rm_eo;
 
-        // Stop after first substitution unless we have flag g
-        if (!(command->sflags & 2)) break;
+        if (!(command->sflags & SFLAG_g)) break;
       }
+      len += bonk;
 
       // If we made any changes, finish off l2 and swap it for line
       if (l2) {
@@ -518,8 +576,7 @@
       }
 
       if (mflags) {
-        // flag p
-        if (command->sflags & 4) emit(line, len, eol);
+        if (command->sflags & SFLAG_p) emit(line, len, eol);
 
         tea = 1;
         if (command->w) goto writenow;
@@ -529,6 +586,8 @@
       char *name;
 
 writenow:
+      if (FLAG(tarxform)) error_exit("tilt");
+
       // Swap out emit() context
       fd = TT.fdout;
       noeol = TT.noeol;
@@ -572,9 +631,10 @@
     command = command->next;
   }
 
+done:
   if (line && !FLAG(n)) emit(line, len, eol);
 
-done:
+  // TODO: should "sed -z ax" use \n instead of NUL?
   if (dlist_terminate(append)) while (append) {
     struct append *a = append->next;
 
@@ -583,7 +643,7 @@
 
       // Force newline if noeol pending
       if (fd != -1) {
-        if (TT.noeol) xwrite(TT.fdout, "\n", 1);
+        if (TT.noeol) xwrite(TT.fdout, &TT.delim, 1);
         TT.noeol = 0;
         xsendfile(fd, TT.fdout);
         close(fd);
@@ -594,6 +654,12 @@
     append = a;
   }
   free(line);
+
+  if (TT.tarxlen) {
+    dprintf(TT.fdout, "%08x", --TT.tarxlen);
+    writeall(TT.fdout, TT.tarxform, TT.tarxlen);
+    TT.tarxlen = 0;
+  }
 }
 
 // Callback called on each input file
@@ -736,6 +802,16 @@
     }
     if (!*line) return;
 
+    if (FLAG(tarxform) && strstart(&line, "flags=")) {
+      TT.xflags = 7;
+      while (0<=(i = stridx("rRsShH", *line))) {
+        if (i&1) TT.xflags |= 1<<(i>>1);
+        else TT.xflags &= ~(1<<(i>>1));
+        line++;
+      }
+      continue;
+    }
+
     // Start by writing data into toybuf.
 
     errstart = line;
@@ -761,7 +837,7 @@
         if (!(s = unescape_delimited_string(&line, 0))) goto error;
         if (!*s) command->rmatch[i] = 0;
         else {
-          xregcomp((void *)reg, s, REG_EXTENDED*!!FLAG(r));
+          xregcomp((void *)reg, s, REG_EXTENDED*FLAG(r));
           command->rmatch[i] = reg-toybuf;
           reg += sizeof(regex_t);
         }
@@ -839,27 +915,36 @@
       i = command->arg1;
       command->arg1 = command->arg2;
       command->arg2 = i;
+      command->sflags = TT.xflags*SFLAG_R;
 
       // get flags
       for (line++; *line; line++) {
         long l;
 
         if (isspace(*line) && *line != '\n') continue;
-
         if (0 <= (l = stridx("igpx", *line))) command->sflags |= 1<<l;
         else if (*line == 'I') command->sflags |= 1<<0;
-        else if (!(command->sflags>>4) && 0<(l = strtol(line, &line, 10))) {
-          command->sflags |= l << 4;
+        else if (FLAG(tarxform) && 0 <= (l = stridx("RSH", *line)))
+          command->sflags |= SFLAG_R<<l;
+        // Given that the default is rsh all enabled... why do these exist?
+        else if (FLAG(tarxform) && 0 <= (l = stridx("rsh", *line)))
+          command->sflags &= ~(SFLAG_R<<l);
+        else if (!(command->sflags>>8) && 0<(l = strtol(line, &line, 10))) {
+          command->sflags |= l << 8;
           line--;
         } else break;
       }
-      flags = (FLAG(r) || (command->sflags&8)) ? REG_EXTENDED : 0;
-      if (command->sflags&1) flags |= REG_ICASE;
+      flags = (FLAG(r) || (command->sflags & SFLAG_x)) ? REG_EXTENDED : 0;
+      if (command->sflags & SFLAG_i) flags |= REG_ICASE;
 
       // We deferred actually parsing the regex until we had the s///i flag
       // allocating the space was done by extend_string() above
       if (!*TT.remember) command->arg1 = 0;
-      else xregcomp((void *)(command->arg1+(char *)command),TT.remember,flags);
+      else {
+        xregcomp((void *)(command->arg1+(char *)command), TT.remember, flags);
+        if (FLAG(tarxform) && TT.remember[strlen(TT.remember)-1]=='/')
+          command->sflags |= SFLAG_slash;
+      }
       free(TT.remember);
       TT.remember = 0;
       if (*line == 'w') {
@@ -980,11 +1065,17 @@
   error_exit("bad pattern '%s'@%ld (%c)", errstart, line-errstart+1L, *line);
 }
 
+// Is the pointer "find" within the string "range".
+static int instr(char *find, char *range)
+{
+  return find>=range && range+strlen(range)>=find;
+}
+
 void sed_main(void)
 {
-  struct arg_list *al;
-  char **args = toys.optargs;
+  char **args = toys.optargs, **aa;
 
+  if (FLAG(tarxform)) toys.optflags |= FLAG_z;
   if (!FLAG(z)) TT.delim = '\n';
 
   // Lie to autoconf when it asks stupid questions, so configure regexes
@@ -1006,13 +1097,18 @@
     (TT.e = xzalloc(sizeof(struct arg_list)))->arg = *(args++);
   }
 
-  // Option parsing infrastructure can't interlace "-e blah -f blah -e blah"
-  // so handle all -e, then all -f. (At least the behavior's consistent.)
-
-  for (al = TT.e; al; al = al->next) parse_pattern(&al->arg, strlen(al->arg));
+  // -e and -f care about order, so use argv[] to recreate original order
+  for (aa = toys.argv+1; *aa; aa++) {
+    if (TT.e && instr(TT.e->arg, *aa)) {
+      parse_pattern(&TT.e->arg, strlen(TT.e->arg));
+      free(llist_pop(&TT.e));
+    }
+    if (TT.f && instr(TT.f->arg, *aa)) {
+      do_lines(xopenro(TT.f->arg), TT.delim, parse_pattern);
+      free(llist_pop(&TT.f));
+    }
+  }
   parse_pattern(0, 0);
-  for (al = TT.f; al; al = al->next)
-    do_lines(xopenro(al->arg), TT.delim, parse_pattern);
   dlist_terminate(TT.pattern);
   if (TT.nextlen) error_exit("no }");  
 
@@ -1028,5 +1124,5 @@
     sed_line(0, 0);
   }
 
-  // todo: need to close fd when done for TOYBOX_FREE?
+  // TODO: need to close fd when done for TOYBOX_FREE?
 }
diff --git a/toys/posix/sleep.c b/toys/posix/sleep.c
index 73f03fb..0eb2270 100644
--- a/toys/posix/sleep.c
+++ b/toys/posix/sleep.c
@@ -11,7 +11,7 @@
   bool "sleep"
   default y
   help
-    usage: sleep DURATION
+    usage: sleep DURATION...
 
     Wait before exiting.
 
@@ -24,7 +24,10 @@
 void sleep_main(void)
 {
   struct timespec ts;
+  char **args;
 
-  xparsetimespec(*toys.optargs, &ts);
-  toys.exitval = !!nanosleep(&ts, NULL);
+  for (args = toys.optargs; !toys.exitval && *args; args++) {
+    xparsetimespec(*args, &ts);
+    toys.exitval = !!nanosleep(&ts, NULL);
+  }
 }
diff --git a/toys/posix/sort.c b/toys/posix/sort.c
index c06b2a5..c0d312d 100644
--- a/toys/posix/sort.c
+++ b/toys/posix/sort.c
@@ -7,7 +7,7 @@
  * Deviations from POSIX: Lots.
  * We invented -x
 
-USE_SORT(NEWTOY(sort, USE_SORT_FLOAT("g")"S:T:m" "o:k*t:" "xVbMcszdfirun", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
+USE_SORT(NEWTOY(sort, USE_SORT_FLOAT("g")"S:T:m" "o:k*t:" "xVbMCcszdfirun", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
 
 config SORT
   bool "sort"
@@ -21,7 +21,8 @@
     -u	Unique lines only
     -n	Numeric order (instead of alphabetical)
     -b	Ignore leading blanks (or trailing blanks in second part of key)
-    -c	Check whether input is sorted
+    -C	Check whether input is sorted
+    -c	Warn if input is unsorted
     -d	Dictionary order (use alphanumeric and whitespace chars only)
     -f	Force uppercase (case insensitive sort)
     -i	Ignore nonprinting characters
@@ -282,9 +283,12 @@
   *pline = 0;
 
   // handle -c here so we don't allocate more memory than necessary.
-  if (FLAG(c)) {
-    if (TT.lines && compare_keys((void *)&TT.lines, &line)>-!!FLAG(u))
-      error_exit("%s: Check line %u\n", TT.name, TT.linecount);
+  if (FLAG(C)||FLAG(c)) {
+    if (TT.lines && compare_keys((void *)&TT.lines, &line)>-FLAG(u)) {
+      toys.exitval = 1;
+      if (FLAG(C)) xexit();
+      error_exit("%s: Check line %u", TT.name, TT.linecount+1);
+    }
     free(TT.lines);
     TT.lines = (void *)line;
   } else {
@@ -299,7 +303,7 @@
 static void sort_read(int fd, char *name)
 {
   TT.name = name;
-  do_lines(fd, FLAG(z) ? '\0' : '\n', sort_lines);
+  do_lines(fd, '\n'*!FLAG(z), sort_lines);
 }
 
 void sort_main(void)
@@ -339,10 +343,9 @@
           flag = 1<<(optlist-temp2+strlen(optlist)-1);
 
           // Was it a flag that can apply to a key?
-          if (!temp2 || flag>FLAG_x || (flag&(FLAG_u|FLAG_c|FLAG_s|FLAG_z))) {
-            toys.exitval = 2;
+          if (!temp2 || flag>FLAG_x || (flag&(FLAG_u|FLAG_c|FLAG_s|FLAG_z)))
             error_exit("Unknown key option.");
-          }
+
           // b after , means strip _trailing_ space, not leading.
           if (idx && flag==FLAG_b) flag = FLAG_bb;
           key->flags |= flag;
@@ -362,7 +365,7 @@
 
   // The compare (-c) logic was handled in sort_read(),
   // so if we got here, we're done.
-  if (FLAG(c)) goto exit_now;
+  if (FLAG(C)||FLAG(c)) goto exit_now;
 
   // Perform the actual sort
   qsort(TT.lines, TT.linecount, sizeof(char *), compare_keys);
diff --git a/toys/posix/tail.c b/toys/posix/tail.c
index f34e10c..514bd5b 100644
--- a/toys/posix/tail.c
+++ b/toys/posix/tail.c
@@ -36,8 +36,7 @@
   struct {
     char *path;
     int fd;
-    dev_t dev;
-    ino_t ino;
+    struct dev_ino di;
   } *F;
 )
 
@@ -159,12 +158,12 @@
         continue;
       }
 
-      if (fd<0 || sb.st_dev!=TT.F[i].dev || sb.st_ino!=TT.F[i].ino) {
+      if (fd<0 || !same_dev_ino(&sb, &TT.F[i].di)) {
         if (fd>=0) close(fd);
         if (-1 == (TT.F[i].fd = fd = open(path, O_RDONLY))) continue;
         error_msg("following new file: %s\n", path);
-        TT.F[i].dev = sb.st_dev;
-        TT.F[i].ino = sb.st_ino;
+        TT.F[i].di.dev = sb.st_dev;
+        TT.F[i].di.ino = sb.st_ino;
       } else if (sb.st_size <= (pos = lseek(fd, 0, SEEK_CUR))) {
         if (pos == sb.st_size) continue;
         error_msg("file truncated: %s\n", path);
@@ -201,8 +200,8 @@
     if (FLAG(F)) {
       if (fd != -1) {
         if (fstat(fd, &sb)) perror_exit("%s", name);
-        TT.F[TT.file_no].dev = sb.st_dev;
-        TT.F[TT.file_no].ino = sb.st_ino;
+        TT.F[TT.file_no].di.dev = sb.st_dev;
+        TT.F[TT.file_no].di.ino = sb.st_ino;
       }
       TT.F[TT.file_no].fd = fd;
       TT.F[TT.file_no].path = s;
@@ -290,8 +289,8 @@
   if (!FLAG(n) && !FLAG(c)) {
     char *arg = *args;
 
-    // handle old "-42" style arguments, else default to last 10 lines
-    if (arg && *arg == '-' && arg[1]) {
+    // handle old "-42" / "+42" style arguments, else default to last 10 lines
+    if (arg && (*arg == '-' || *arg == '+') && arg[1]) {
       TT.n = atolx(*(args++));
       toys.optc--;
     } else TT.n = -10;
@@ -302,7 +301,7 @@
   TT.ss = TT.s ? xparsemillitime(TT.s) : 1000;
 
   loopfiles_rw(args,
-    O_RDONLY|WARN_ONLY|LOOPFILES_ANYWAY|(O_CLOEXEC*!(FLAG(f) || FLAG(F))),
+    O_RDONLY|WARN_ONLY|LOOPFILES_ANYWAY|O_CLOEXEC*!(FLAG(f) || FLAG(F)),
     0, do_tail);
 
   // Wait for more data when following files
diff --git a/toys/posix/tar.c b/toys/posix/tar.c
index 9cf1a5c..ea8edbf 100644
--- a/toys/posix/tar.c
+++ b/toys/posix/tar.c
@@ -14,10 +14,13 @@
  *
  * Toybox will never implement the "pax" command as a matter of policy.
  *
+ * TODO: --wildcard state changes aren't positional.
+ * We always --verbatim-files-from
  * Why --exclude pattern but no --include? tar cvzf a.tgz dir --include '*.txt'
- *
+ * No --no-null because the args infrastructure isn't ready.
+ * Until args.c learns about no- toggles, --no-thingy always wins over --thingy
 
-USE_TAR(NEWTOY(tar, "&(strip-components)#(selinux)(restrict)(full-time)(no-recursion)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(mode):(mtime):(group):(owner):(to-command):o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)I(use-compress-program):J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*C(directory):f(file):a[!txc][!jzJa]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_TAR(NEWTOY(tar, "&(no-ignore-case)(ignore-case)(no-anchored)(anchored)(no-wildcards)(wildcards)(no-wildcards-match-slash)(wildcards-match-slash)(show-transformed-names)(selinux)(restrict)(full-time)(no-recursion)(null)(numeric-owner)(no-same-permissions)(overwrite)(exclude)*(sort);:(mode):(mtime):(group):(owner):(to-command):~(strip-components)(strip)#~(transform)(xform)*o(no-same-owner)p(same-permissions)k(keep-old)c(create)|h(dereference)x(extract)|t(list)|v(verbose)J(xz)j(bzip2)z(gzip)S(sparse)O(to-stdout)P(absolute-names)m(touch)X(exclude-from)*T(files-from)*I(use-compress-program):C(directory):f(file):as[!txc][!jzJa]", TOYFLAG_USR|TOYFLAG_BIN))
 
 config TAR
   bool "tar"
@@ -30,9 +33,10 @@
     Options:
     c  Create                x  Extract               t  Test (list)
     f  tar FILE (default -)  C  Change to DIR first   v  Verbose display
-    o  Ignore owner          h  Follow symlinks       m  Ignore mtime
     J  xz compression        j  bzip2 compression     z  gzip compression
+    o  Ignore owner          h  Follow symlinks       m  Ignore mtime
     O  Extract to stdout     X  exclude names in FILE T  include names in FILE
+    s  Sort dirs (--sort)
 
     --exclude        FILENAME to exclude  --full-time         Show seconds with -tv
     --mode MODE      Adjust permissions   --owner NAME[:UID]  Set file ownership
@@ -40,32 +44,41 @@
     --sparse         Record sparse files  --selinux           Save/restore labels
     --restrict       All under one dir    --no-recursion      Skip dir contents
     --numeric-owner  Use numeric uid/gid, not user/group names
+    --null           Filenames in -T FILE are null-separated, not newline
     --strip-components NUM  Ignore first NUM directory components when extracting
+    --xform=SED      Modify filenames via SED expression (ala s/find/replace/g)
     -I PROG          Filter through PROG to compress or PROG -d to decompress
+
+    Filename filter types. Create command line args aren't filtered, extract
+    defaults to --anchored, --exclude defaults to --wildcards-match-slash,
+    use no- prefix to disable:
+
+    --anchored  Match name not path       --ignore-case       Case insensitive
+    --wildcards Expand *?[] like shell    --wildcards-match-slash
 */
 
 #define FOR_tar
 #include "toys.h"
 
 GLOBALS(
-  char *f, *C;
-  struct arg_list *T, *X;
-  char *I, *to_command, *owner, *group, *mtime, *mode;
+  char *f, *C, *I;
+  struct arg_list *T, *X, *xform;
+  long strip;
+  char *to_command, *owner, *group, *mtime, *mode, *sort;
   struct arg_list *exclude;
-  long strip_components;
 
   struct double_list *incl, *excl, *seen;
   struct string_list *dirs;
-  char *cwd;
-  int fd, ouid, ggid, hlc, warn, adev, aino, sparselen, pid;
+  char *cwd, **xfsed;
+  int fd, ouid, ggid, hlc, warn, sparselen, pid, xfpipe[2];
+  struct dev_ino archive_di;
   long long *sparse;
   time_t mtt;
 
   // hardlinks seen so far (hlc many)
   struct {
     char *arg;
-    ino_t ino;
-    dev_t dev;
+    struct dev_ino di;
   } *hlx;
 
   // Parsed information about a tar header.
@@ -80,8 +93,9 @@
   } hdr;
 )
 
+// The on-disk 512 byte record structure.
 struct tar_hdr {
-  char name[100], mode[8], uid[8], gid[8],size[12], mtime[12], chksum[8],
+  char name[100], mode[8], uid[8], gid[8], size[12], mtime[12], chksum[8],
        type, link[100], magic[8], uname[32], gname[32], major[8], minor[8],
        prefix[155], padd[12];
 };
@@ -158,14 +172,51 @@
   if (len>check) write_prefix_block(data, len+1, type);
 }
 
+static int do_filter(char *pattern, char *name, long long flags)
+{
+  int ign = !!(flags&FLAG_ignore_case), wild = !!(flags&FLAG_wildcards),
+      slash = !!(flags&FLAG_wildcards_match_slash), len;
+
+  if (wild || slash) {
+    // 1) match can end with / 2) maybe case insensitive 2) maybe * matches /
+    if (!fnmatch(pattern, name, FNM_LEADING_DIR+FNM_CASEFOLD*ign+FNM_PATHNAME*slash))
+      return 1;
+  } else {
+    len = strlen(pattern);
+    if (!(ign ? strncasecmp : strncmp)(pattern, name, len))
+      if (!name[len] || name[len]=='/') return 1;
+  }
+
+  return 0;
+}
+
 static struct double_list *filter(struct double_list *lst, char *name)
 {
   struct double_list *end = lst;
+  long long flags = toys.optflags;
+  char *ss;
 
-  if (lst)
-    // constant is FNM_LEADING_DIR
-    do if (!fnmatch(lst->data, name, 1<<3)) return lst;
-    while (end != (lst = lst->next));
+  if (!lst || !*name) return 0;
+
+  // --wildcards-match-slash implies --wildcards because I couldn't figure
+  // out a graceful way to explain why it DIDN'T in the help text. We don't
+  // do the positional enable/disable thing (would need to annotate at list
+  // creation, maybe a TODO item).
+
+  // Set defaults for filter type, and apply --no-flags
+  if (lst == TT.excl) flags |= FLAG_wildcards_match_slash;
+  else flags |= FLAG_anchored;
+  flags &= (~(flags&(FLAG_no_ignore_case|FLAG_no_anchored|FLAG_no_wildcards|FLAG_no_wildcards_match_slash)))>>1;
+  if (flags&FLAG_no_wildcards) flags &= ~FLAG_wildcards_match_slash;
+
+  // The +1 instead of ++ is in case of conseutive slashes
+  do {
+    if (do_filter(lst->data, name, flags)) return lst;
+    if (!(flags & FLAG_anchored)) for (ss = name; *ss; ss++) {
+      if (*ss!='/' || !ss[1]) continue;
+      if (do_filter(lst->data, ss+1, flags)) return lst;
+    }
+  } while (end != (lst = lst->next));
 
   return 0;
 }
@@ -187,6 +238,28 @@
   (*b)[len] = 0;
 }
 
+static char *xform(char **name, char type)
+{
+  char buf[9], *end;
+  off_t len;
+
+  if (!TT.xform) return 0;
+
+  buf[8] = 0;
+  if (dprintf(TT.xfpipe[0], "%s%c%c", *name, type, 0) != strlen(*name)+2
+    || readall(TT.xfpipe[1], buf, 8) != 8
+    || !(len = estrtol(buf, &end, 16)) || errno ||*end) error_exit("bad xform");
+  xreadall(TT.xfpipe[1], *name = xmalloc(len+1), len);
+  (*name)[len] = 0;
+
+  return *name;
+}
+
+int dirtree_sort(struct dirtree **aa, struct dirtree **bb)
+{
+  return (FLAG(ignore_case) ? strcasecmp : strcmp)(aa[0]->name, bb[0]->name);
+}
+
 // callback from dirtree to create archive
 static int add_to_tar(struct dirtree *node)
 {
@@ -194,44 +267,58 @@
   struct tar_hdr hdr;
   struct passwd *pw = pw;
   struct group *gr = gr;
-  int i, fd = -1, norecurse = FLAG(no_recursion);
-  char *name, *lnk, *hname;
+  int i, fd = -1, recurse = 0;
+  char *name, *lnk, *hname, *xfname = 0;
 
   if (!dirtree_notdotdot(node)) return 0;
-  if (TT.adev == st->st_dev && TT.aino == st->st_ino) {
+  if (same_dev_ino(st, &TT.archive_di)) {
     error_msg("'%s' file is the archive; not dumped", node->name);
     return 0;
   }
 
   i = 1;
   name = hname = dirtree_path(node, &i);
+  if (filter(TT.excl, name)) goto done;
 
-  // exclusion defaults to --no-anchored and --wildcards-match-slash
-  for (lnk = name; *lnk;) {
-    if (filter(TT.excl, lnk)) {
-      norecurse++;
+  if ((FLAG(s)|FLAG(sort)) && !FLAG(no_recursion)) {
+    if (S_ISDIR(st->st_mode) && !node->again) {
+      free(name);
 
-      goto done;
+      return DIRTREE_BREADTH;
+    } else if ((node->again&DIRTREE_BREADTH) && node->child) {
+      struct dirtree *dt, **sort = xmalloc(sizeof(void *)*node->extra);
+
+      for (node->extra = 0, dt = node->child; dt; dt = dt->next) 
+        sort[node->extra++] = dt;
+      qsort(sort, node->extra--, sizeof(void *), (void *)dirtree_sort);
+      node->child = *sort;
+      for (i = 0; i<node->extra; i++) sort[i]->next = sort[i+1];
+      sort[i]->next = 0;
+      free(sort);
+
+      // fall through to add directory
     }
-    while (*lnk && *lnk!='/') lnk++;
-    while (*lnk=='/') lnk++;
   }
 
   // Consume the 1 extra byte alocated in dirtree_path()
-  if (S_ISDIR(st->st_mode) && name[i-1] != '/') strcat(name, "/");
+  if (S_ISDIR(st->st_mode) && (lnk = name+strlen(name))[-1] != '/')
+    strcpy(lnk, "/");
 
   // remove leading / and any .. entries from saved name
-  if (!FLAG(P)) while (*hname == '/') hname++;
-  for (lnk = hname;;) {
-    if (!(lnk = strstr(lnk, ".."))) break;
-    if (lnk == hname || lnk[-1] == '/') {
-      if (!lnk[2]) goto done;
-      if (lnk[2]=='/') {
-        lnk = hname = lnk+3;
-        continue;
+  if (!FLAG(P)) {
+    while (*hname == '/') hname++;
+    for (lnk = hname;;) {
+      if (!(lnk = strstr(lnk, ".."))) break;
+      if (lnk == hname || lnk[-1] == '/') {
+        if (!lnk[2]) goto done;
+        if (lnk[2]=='/') {
+          lnk = hname = lnk+3;
+          continue;
+        }
       }
+      lnk += 2;
     }
-    lnk += 2;
+    if (!*hname) hname = "./";
   }
   if (!*hname) goto done;
 
@@ -241,13 +328,12 @@
     TT.warn = 0;
   }
 
+  // Override dentry data from command line and fill out header data
   if (TT.owner) st->st_uid = TT.ouid;
   if (TT.group) st->st_gid = TT.ggid;
   if (TT.mode) st->st_mode = string_to_mode(TT.mode, st->st_mode);
   if (TT.mtime) st->st_mtime = TT.mtt;
-
   memset(&hdr, 0, sizeof(hdr));
-  strncpy(hdr.name, hname, sizeof(hdr.name));
   ITOO(hdr.mode, st->st_mode &07777);
   ITOO(hdr.uid, st->st_uid);
   ITOO(hdr.gid, st->st_gid);
@@ -255,40 +341,39 @@
   ITOO(hdr.mtime, st->st_mtime);
   strcpy(hdr.magic, "ustar  ");
 
-  // Hard link or symlink? i=0 neither, i=1 hardlink, i=2 symlink
-
   // Are there hardlinks to a non-directory entry?
+  lnk = 0;
   if (st->st_nlink>1 && !S_ISDIR(st->st_mode)) {
     // Have we seen this dev&ino before?
-    for (i = 0; i<TT.hlc; i++) {
-      if (st->st_ino == TT.hlx[i].ino && st->st_dev == TT.hlx[i].dev)
-        break;
-    }
-    if (i != TT.hlc) {
-      lnk = TT.hlx[i].arg;
-      i = 1;
-    } else {
+    for (i = 0; i<TT.hlc; i++) if (same_dev_ino(st, &TT.hlx[i].di)) break;
+    if (i != TT.hlc) lnk = TT.hlx[i].arg;
+    else {
       // first time we've seen it. Store as normal file, but remember it.
       if (!(TT.hlc&255))
         TT.hlx = xrealloc(TT.hlx, sizeof(*TT.hlx)*(TT.hlc+256));
       TT.hlx[TT.hlc].arg = xstrdup(hname);
-      TT.hlx[TT.hlc].ino = st->st_ino;
-      TT.hlx[TT.hlc].dev = st->st_dev;
+      TT.hlx[TT.hlc].di.ino = st->st_ino;
+      TT.hlx[TT.hlc].di.dev = st->st_dev;
       TT.hlc++;
-      i = 0;
     }
-  } else i = 0;
+  }
 
-  // Handle file types
-  if (i || S_ISLNK(st->st_mode)) {
-    hdr.type = '1'+!i;
-    if (!i && !(lnk = xreadlink(name))) {
+  xfname = xform(&hname, 'r');
+  strncpy(hdr.name, hname, sizeof(hdr.name));
+
+  // Handle file types: 0=reg, 1=hardlink, 2=sym, 3=chr, 4=blk, 5=dir, 6=fifo
+  if (lnk || S_ISLNK(st->st_mode)) {
+    hdr.type = '1'+!lnk;
+    if (lnk) {
+      if (!xform(&lnk, 'h')) lnk = xstrdup(lnk);
+    } else if (!(lnk = xreadlink(name))) {
       perror_msg("readlink");
       goto done;
-    }
+    } else xform(&lnk, 's');
+
     maybe_prefix_block(lnk, sizeof(hdr.link), 'K');
     strncpy(hdr.link, lnk, sizeof(hdr.link));
-    if (!i) free(lnk);
+    free(lnk);
   } else if (S_ISREG(st->st_mode)) {
     hdr.type = '0';
     ITOO(hdr.size, st->st_size);
@@ -348,6 +433,7 @@
     // Before we write the header, make sure we can read the file
     if ((fd = open(name, O_RDONLY)) < 0) {
       perror_msg("can't open '%s'", name);
+      free(name);
 
       return 0;
     }
@@ -420,10 +506,13 @@
     if (st->st_size%512) writeall(TT.fd, toybuf, (512-(st->st_size%512)));
     close(fd);
   }
+  recurse = !FLAG(no_recursion);
+
 done:
+  free(xfname);
   free(name);
 
-  return (DIRTREE_RECURSE|(FLAG(h)?DIRTREE_SYMFOLLOW:0))*!norecurse;
+  return recurse*(DIRTREE_RECURSE|DIRTREE_SYMFOLLOW*FLAG(h));
 }
 
 static void wsettime(char *s, long long sec)
@@ -518,18 +607,9 @@
   close(fd);
 }
 
-static void extract_to_disk(void)
+static void extract_to_disk(char *name)
 {
-  char *name = TT.hdr.name;
-  int ala = TT.hdr.mode, strip;
-
-  for (strip = 0; strip < TT.strip_components; strip++) {
-    char *s = strchr(name, '/');
-
-    if (s && s[1]) name = s+1;
-    else if (S_ISDIR(ala)) return;
-    else break;
-  }
+  int ala = TT.hdr.mode;
 
   if (dirflush(name, S_ISDIR(ala))) {
     if (S_ISREG(ala) && !TT.hdr.link_target) skippy(TT.hdr.size);
@@ -573,7 +653,7 @@
     if (TT.owner) TT.hdr.uid = TT.ouid;
     else if (!FLAG(numeric_owner) && *TT.hdr.uname) {
       struct passwd *pw = bufgetpwnamuid(TT.hdr.uname, 0);
-      if (pw && (TT.owner || !FLAG(numeric_owner))) TT.hdr.uid = pw->pw_uid;
+      if (pw) TT.hdr.uid = pw->pw_uid;
     }
 
     if (TT.group) TT.hdr.gid = TT.ggid;
@@ -610,7 +690,7 @@
   struct tar_hdr tar;
   int i, sefd = -1, and = 0;
   unsigned maj, min;
-  char *s;
+  char *s, *name;
 
   for (;;) {
     if (first) {
@@ -776,9 +856,31 @@
       }
     }
 
-    // Skip excluded files
-    if (filter(TT.excl, TT.hdr.name) || (TT.incl && !delete))
+    // Skip excluded files, filtering on the untransformed name.
+    if (filter(TT.excl, name = TT.hdr.name) || (TT.incl && !delete)) {
       skippy(TT.hdr.size);
+      goto done;
+    }
+
+    // We accept --show-transformed but always do, so it's a NOP.
+    name = TT.hdr.name;
+    if (xform(&name, 'r')) {
+      free(TT.hdr.name);
+      TT.hdr.name = name;
+    }
+    if ((i = "\0hs"[stridx("12", tar.type)+1])) xform(&TT.hdr.link_target, i);
+
+    for (i = 0; i<TT.strip; i++) {
+      char *s = strchr(name, '/');
+
+      if (s && s[1]) name = s+1;
+      else {
+        if (S_ISDIR(TT.hdr.mode)) *name = 0;
+        break;
+      }
+    }
+
+    if (!*name) skippy(TT.hdr.size);
     else if (FLAG(t)) {
       if (FLAG(v)) {
         struct tm *lc = localtime(TT.mtime ? &TT.mtt : &TT.hdr.mtime);
@@ -796,12 +898,13 @@
         printf("  %d-%02d-%02d %02d:%02d%s ", 1900+lc->tm_year, 1+lc->tm_mon,
           lc->tm_mday, lc->tm_hour, lc->tm_min, FLAG(full_time) ? perm : "");
       }
-      printf("%s", TT.hdr.name);
-      if (TT.hdr.link_target) printf(" -> %s", TT.hdr.link_target);
+      printf("%s", name);
+      if (TT.hdr.link_target)
+        printf(" %s %s", tar.type=='2' ? "->" : "link to", TT.hdr.link_target);
       xputc('\n');
       skippy(TT.hdr.size);
     } else {
-      if (FLAG(v)) printf("%s\n", TT.hdr.name);
+      if (FLAG(v)) printf("%s\n", name);
       if (FLAG(O)) sendfile_sparse(1);
       else if (FLAG(to_command)) {
         if (S_ISREG(TT.hdr.mode)) {
@@ -810,7 +913,7 @@
           xsetenv("TAR_FILETYPE", "f");
           xsetenv(xmprintf("TAR_MODE=%o", TT.hdr.mode), 0);
           xsetenv(xmprintf("TAR_SIZE=%lld", TT.hdr.ssize), 0);
-          xsetenv("TAR_FILENAME", TT.hdr.name);
+          xsetenv("TAR_FILENAME", name);
           xsetenv("TAR_UNAME", TT.hdr.uname);
           xsetenv("TAR_GNAME", TT.hdr.gname);
           xsetenv(xmprintf("TAR_MTIME=%llo", (long long)TT.hdr.mtime), 0);
@@ -818,14 +921,15 @@
           xsetenv(xmprintf("TAR_GID=%o", TT.hdr.gid), 0);
 
           pid = xpopen((char *[]){"sh", "-c", TT.to_command, NULL}, &fd, 0);
-          // todo: short write exits tar here, other skips data.
+          // TODO: short write exits tar here, other skips data.
           sendfile_sparse(fd);
           fd = xpclose_both(pid, 0);
           if (fd) error_msg("%d: Child returned %d", pid, fd);
         }
-      } else extract_to_disk();
+      } else extract_to_disk(name);
     }
 
+done:
     if (sefd != -1) {
       // zero length write resets fscreate context to default
       (void)write(sefd, 0, 0);
@@ -848,7 +952,7 @@
 
   dlist_add(list, n);
   if (i && n[i-1]=='\n') i--;
-  while (i && n[i-1] == '/') i--;
+  while (i>1 && n[i-1] == '/') i--;
   n[i] = 0;
 }
 
@@ -858,11 +962,15 @@
   if (pline) trim2list(TT.X ? &TT.excl : &TT.incl, *pline);
 }
 
+static  char *get_archiver()
+{
+  return TT.I ? : FLAG(z) ? "gzip" : FLAG(j) ? "bzip2" : "xz";
+}
+
 void tar_main(void)
 {
-  char *s, **args = toys.optargs,
-    *archiver = FLAG(I) ? TT.I : (FLAG(z) ? "gzip" : (FLAG(J) ? "xz":"bzip2"));
-  int len = 0;
+  char *s, **xfsed, **args = toys.optargs;
+  int len = 0, ii;
 
   // Needed when extracting to command
   signal(SIGPIPE, SIG_IGN);
@@ -885,12 +993,16 @@
   }
   if (TT.mtime) xparsedate(TT.mtime, &TT.mtt, (void *)&s, 1);
 
+  // TODO: collect filter types here and annotate saved include/exclude?
+
   // Collect file list.
   for (; TT.exclude; TT.exclude = TT.exclude->next)
     trim2list(&TT.excl, TT.exclude->arg);
   for (;TT.X; TT.X = TT.X->next) do_lines(xopenro(TT.X->arg), '\n', do_XT);
   for (args = toys.optargs; *args; args++) trim2list(&TT.incl, *args);
-  for (;TT.T; TT.T = TT.T->next) do_lines(xopenro(TT.T->arg), '\n', do_XT);
+  // -T is always --verbatim-files-from: no quote removal or -arg handling
+  for (;TT.T; TT.T = TT.T->next)
+    do_lines(xopenro(TT.T->arg), '\n'*!FLAG(null), do_XT);
 
   // If include file list empty, don't create empty archive
   if (FLAG(c)) {
@@ -898,6 +1010,23 @@
     TT.fd = 1;
   }
 
+  if (TT.xform) {
+    struct arg_list *al;
+
+    for (ii = 0, al = TT.xform; al; al = al->next) ii++;
+    xfsed = xmalloc((ii+2)*2*sizeof(char *));
+    xfsed[0] = "sed";
+    xfsed[1] = "--tarxform";
+    for (ii = 2, al = TT.xform; al; al = al->next) {
+      xfsed[ii++] = "-e";
+      xfsed[ii++] = al->arg;
+    }
+    xfsed[ii] = 0;
+    TT.xfpipe[0] = TT.xfpipe[1] = -1;
+    xpopen_both(xfsed, TT.xfpipe);
+    free(xfsed);
+  }
+
   // nommu reentry for nonseekable input skips this, parent did it for us
   if (toys.stacktop) {
     if (TT.f && strcmp(TT.f, "-"))
@@ -915,8 +1044,8 @@
     struct stat st;
 
     if (!fstat(TT.fd, &st)) {
-      TT.aino = st.st_ino;
-      TT.adev = st.st_dev;
+      TT.archive_di.ino = st.st_ino;
+      TT.archive_di.dev = st.st_dev;
     }
   }
 
@@ -930,7 +1059,7 @@
       if (len!=512 || !is_tar_header(hdr)) {
         // detect gzip and bzip signatures
         if (SWAP_BE16(*(short *)hdr)==0x1f8b) toys.optflags |= FLAG_z;
-        else if (!memcmp(hdr, "BZh", 3)) toys.optflags |= FLAG_j;
+        else if (!smemcmp(hdr, "BZh", 3)) toys.optflags |= FLAG_j;
         else if (peek_be(hdr, 7) == 0xfd377a585a0000UL) toys.optflags |= FLAG_J;
         else error_exit("Not tar");
 
@@ -942,11 +1071,11 @@
     if (FLAG(j)||FLAG(z)||FLAG(I)||FLAG(J)) {
       int pipefd[2] = {hdr ? -1 : TT.fd, -1}, i, pid;
       struct string_list *zcat = FLAG(I) ? 0 : find_in_path(getenv("PATH"),
-        FLAG(j) ? "bzcat" : FLAG(J) ? "xzcat" : "zcat");
+        FLAG(z) ? "zcat" : FLAG(j) ? "bzcat" : "xzcat");
 
       // Toybox provides more decompressors than compressors, so try them first
       TT.pid = xpopen_both(zcat ? (char *[]){zcat->str, 0} :
-        (char *[]){archiver, "-d", 0}, pipefd);
+        (char *[]){get_archiver(), "-d", 0}, pipefd);
       if (CFG_TOYBOX_FREE) llist_traverse(zcat, free);
 
       if (!hdr) {
@@ -987,7 +1116,7 @@
     unpack_tar(hdr);
     dirflush(0, 0);
     // Shut up archiver about inability to write all trailing NULs to pipe buf
-    if (TT.pid>0) kill(TT.pid, 9);
+    while (0<read(TT.fd, toybuf, sizeof(toybuf)));
 
     // Each time a TT.incl entry is seen it's moved to the end of the list,
     // with TT.seen pointing to first seen list entry. Anything between
@@ -1018,16 +1147,23 @@
     if (FLAG(j)||FLAG(z)||FLAG(I)||FLAG(J)) {
       int pipefd[2] = {-1, TT.fd};
 
-      xpopen_both((char *[]){archiver, 0}, pipefd);
+      TT.pid = xpopen_both((char *[]){get_archiver(), 0}, pipefd);
       close(TT.fd);
       TT.fd = pipefd[0];
     }
     do {
       TT.warn = 1;
-      dirtree_flagread(dl->data, FLAG(h) ? DIRTREE_SYMFOLLOW : 0, add_to_tar);
+      dirtree_flagread(dl->data,
+        DIRTREE_SYMFOLLOW*FLAG(h)|DIRTREE_BREADTH*(FLAG(sort)|FLAG(s)),
+        add_to_tar);
     } while (TT.incl != (dl = dl->next));
 
     writeall(TT.fd, toybuf, 1024);
+    close(TT.fd);
+  }
+  if (TT.pid) {
+    TT.pid = xpclose_both(TT.pid, 0);
+    if (TT.pid) toys.exitval = TT.pid;
   }
   if (toys.exitval) error_msg("had errors");
 
diff --git a/toys/posix/test.c b/toys/posix/test.c
index 3fadf3a..cdb13e2 100644
--- a/toys/posix/test.c
+++ b/toys/posix/test.c
@@ -4,10 +4,11 @@
  *
  * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html
  *
- * TODO sh [[ ]] options: <   aaa<bbb  >   bbb>aaa   ~= regex
+ * Deviations from posix: -k, [[ < > =~ ]]
 
 USE_TEST(NEWTOY(test, 0, TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_NOHELP|TOYFLAG_MAYFORK))
 USE_TEST_GLUE(OLDTOY([, test, TOYFLAG_BIN|TOYFLAG_MAYFORK|TOYFLAG_NOHELP))
+USE_SH(OLDTOY([[, test, TOYFLAG_NOFORK|TOYFLAG_NOHELP))
 
 config TEST
   bool "test"
@@ -15,23 +16,25 @@
   help
     usage: test [-bcdefghLPrSsuwx PATH] [-nz STRING] [-t FD] [X ?? Y]
 
-    Return true or false by performing tests. (With no arguments return false.)
+    Return true or false by performing tests. No arguments is false, one argument
+    is true if not empty string.
 
     --- Tests with a single argument (after the option):
     PATH is/has:
       -b  block device   -f  regular file   -p  fifo           -u  setuid bit
-      -c  char device    -g  setgid         -r  read bit       -w  write bit
-      -d  directory      -h  symlink        -S  socket         -x  execute bit
+      -c  char device    -g  setgid         -r  readable       -w  writable
+      -d  directory      -h  symlink        -S  socket         -x  executable
       -e  exists         -L  symlink        -s  nonzero size   -k  sticky bit
     STRING is:
-      -n  nonzero size   -z  zero size      (STRING by itself implies -n)
+      -n  nonzero size   -z  zero size
     FD (integer file descriptor) is:
-      -t  a TTY
+      -t  a TTY          -T  open
 
     --- Tests with one argument on each side of an operator:
     Two strings:
-      =  are identical   !=  differ
-
+      =  are identical   !=  differ         =~  string matches regex
+    Alphabetical sort:
+      <  first is lower  >   first higher
     Two integers:
       -eq  equal         -gt  first > second    -lt  first < second
       -ne  not equal     -ge  first >= second   -le  first <= second
@@ -57,8 +60,24 @@
   if (*count>=3) {
     *count = 3;
     char *s = args[1], *ss = "eqnegtgeltle";
+    // TODO shell integration case insensitivity
     if (!strcmp(s, "=") || !strcmp(s, "==")) return !strcmp(args[0], args[2]);
     if (!strcmp(s, "!=")) return strcmp(args[0], args[2]);
+    if (!strcmp(s, "=~")) {
+      regex_t reg;
+
+      // TODO: regex needs integrated quoting support with the shell.
+      // Ala [[ abc =~ "1"* ]] matches but [[ abc =~ 1"*" ]] does not
+      xregcomp(&reg, args[2], REG_NOSUB); // REG_EXTENDED? REG_ICASE?
+      i = regexec(&reg, args[0], 0, 0, 0);
+      regfree(&reg);
+
+      return !i;
+    }
+    if ((*s=='<' || *s=='>') && !s[1]) {
+      i = strcmp(args[0], args[2]);
+      return (*s=='<') ? i<0 : i>0;
+    }
     if (*s=='-' && strlen(s)==3 && (s = strstr(ss, s+1)) && !((i = s-ss)&1)) {
       long long a = atolx(args[0]), b = atolx(args[2]);
 
@@ -74,12 +93,13 @@
   if (*count>=2 && *s == '-' && s[1] && !s[2]) {
     *count = 2;
     c = s[1];
+    if (c=='a') c = 'e';
     if (-1 != (i = stridx("hLbcdefgkpSusxwr", c))) {
       struct stat st;
 
-      // stat or lstat, then handle rwx and s
+      if (i>=13) return !access(args[1], 1<<(i-13));
+      // stat or lstat, check s
       if (-1 == ((i<2) ? lstat : stat)(args[1], &st)) return 0;
-      if (i>=13) return !!(st.st_mode&(0111<<(i-13)));
       if (c == 's') return !!st.st_size; // otherwise 1<<32 == 0
 
       // handle file type checking and SUID/SGID
@@ -89,6 +109,7 @@
     } else if (c == 'z') return !*args[1];
     else if (c == 'n') return *args[1];
     else if (c == 't') return isatty(atolx(args[1]));
+    else if (c == 'T') return -1 != fcntl(atolx(args[1]), F_GETFL);
   }
   return *count = 0;
 }
@@ -98,13 +119,14 @@
 #define OR  4  // test before -o succeeded since ( so force true
 void test_main(void)
 {
-  char *s;
+  char *s = (void *)1;
   int pos, paren, pstack, result = 0;
 
   toys.exitval = 2;
-  if (CFG_TOYBOX && !strcmp("[", toys.which->name))
-    if (!toys.optc || strcmp("]", toys.optargs[--toys.optc]))
-      error_exit("Missing ']'");
+  if (CFG_TOYBOX && *toys.which->name=='[') {
+    if (toys.optc) for (s = toys.optargs[--toys.optc]; *s==']'; s++);
+    if (*s) error_exit("Missing ']'");
+  }
 
   // loop through command line arguments
   if (toys.optc) for (pos = paren = pstack = 0; ; pos++) {
diff --git a/toys/posix/time.c b/toys/posix/time.c
index 1becad1..078aca5 100644
--- a/toys/posix/time.c
+++ b/toys/posix/time.c
@@ -31,7 +31,7 @@
   long long sec[3];
   int stat, ii, idx, nano[3];
   pid_t pid;
-  char *labels[] = {"\nreal"+!!FLAG(p), "user", "sys"}, **label = labels,
+  char *labels[] = {"\nreal"+FLAG(p), "user", "sys"}, **label = labels,
        *vlabels[] ={"Real", "User", "System"}, tab = toys.optflags ? ' ' : '\t';
 
   if (FLAG(v)) label = vlabels;
diff --git a/toys/posix/touch.c b/toys/posix/touch.c
index 5e33d7f..e687ff8 100644
--- a/toys/posix/touch.c
+++ b/toys/posix/touch.c
@@ -71,7 +71,6 @@
     if (!strcmp(s, "-")) {
       if (!futimens(1, ts)) continue;
     } else {
-      // cheat: FLAG_h is rightmost flag, so its value is 1
       if (!utimensat(AT_FDCWD, s, ts, FLAG(h)*AT_SYMLINK_NOFOLLOW)) continue;
       if (FLAG(c)) continue;
       if (access(s, F_OK) && (-1!=(fd = open(s, O_CREAT, 0666)))) {
diff --git a/toys/posix/ulimit.c b/toys/posix/ulimit.c
index 3797098..642f887 100644
--- a/toys/posix/ulimit.c
+++ b/toys/posix/ulimit.c
@@ -22,7 +22,6 @@
 config ULIMIT
   bool "ulimit"
   default y
-  depends on TOYBOX_PRLIMIT
   help
     usage: ulimit [-P PID] [-SHRacdefilmnpqrstuv] [LIMIT]
 
diff --git a/toys/posix/uname.c b/toys/posix/uname.c
index fe44ced..d11e1e5 100644
--- a/toys/posix/uname.c
+++ b/toys/posix/uname.c
@@ -4,7 +4,7 @@
  *
  * See http://opengroup.org/onlinepubs/9699919799/utilities/uname.html
 
-USE_UNAME(NEWTOY(uname, "aomvrns", TOYFLAG_BIN))
+USE_UNAME(NEWTOY(uname, "paomvrns", TOYFLAG_BIN))
 USE_ARCH(NEWTOY(arch, 0, TOYFLAG_USR|TOYFLAG_BIN))
 USE_LINUX32(NEWTOY(linux32, 0, TOYFLAG_USR|TOYFLAG_BIN))
 
@@ -60,6 +60,7 @@
     }
     xputsn(c);
   }
+  if (FLAG(p)) xputsn(" unknown"+!needspace);
   xputc('\n');
 }
 
diff --git a/toys/posix/uuencode.c b/toys/posix/uuencode.c
index 160954d..3bede30 100644
--- a/toys/posix/uuencode.c
+++ b/toys/posix/uuencode.c
@@ -24,19 +24,19 @@
 {
   char *name = toys.optargs[toys.optc-1], buf[(76/4)*3];
 
-  int i, m = FLAG(m), fd = 0;
+  int i, fd = 0;
 
   if (toys.optc > 1) fd = xopenro(toys.optargs[0]);
 
   base64_init(toybuf);
 
-  xprintf("begin%s 744 %s\n", m ? "-base64" : "", name);
+  xprintf("begin%s 744 %s\n", FLAG(m) ? "-base64" : "", name);
   for (;;) {
     char *in;
 
-    if (!(i = xread(fd, buf, m ? sizeof(buf) : 45))) break;
+    if (!(i = xread(fd, buf, FLAG(m) ? sizeof(buf) : 45))) break;
 
-    if (!m) xputc(i+32);
+    if (!FLAG(m)) xputc(i+32);
     in = buf;
 
     for (in = buf; in-buf < i; ) {
@@ -49,10 +49,11 @@
 
         if (j < bytes) x |= (*(in++) & 0x0ff) << (8*(2-j));
         out = (x>>((3-j)*6)) & 0x3f;
-        xputc(m ? (j > bytes ? '=' : toybuf[out]) : (out ? out + 0x20 : 0x60));
+        xputc(FLAG(m) ? (j > bytes ? '=' : toybuf[out])
+          : (out ? out + 0x20 : 0x60));
       } 
     }
     xputc('\n');
   }
-  xputs(m ? "====" : "end");
+  xputs(FLAG(m) ? "====" : "end");
 }
diff --git a/toys/posix/who.c b/toys/posix/who.c
index 2515af3..2435385 100644
--- a/toys/posix/who.c
+++ b/toys/posix/who.c
@@ -16,7 +16,6 @@
 config WHO
   bool "who"
   default y
-  depends on TOYBOX_UTMPX
   help
     usage: who
 
diff --git a/toys/posix/xargs.c b/toys/posix/xargs.c
index cc3ee3d..67fa3a0 100644
--- a/toys/posix/xargs.c
+++ b/toys/posix/xargs.c
@@ -9,7 +9,7 @@
  * TODO: -L	Max number of lines of input per command
  * TODO: -x	Exit if can't fit everything in one command
 
-USE_XARGS(NEWTOY(xargs, "^E:P#<0=1optrn#<1(max-args)s#0[!0E]", 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))
 
 config XARGS
   bool "xargs"
@@ -184,7 +184,7 @@
 
     if (!(pid = XVFORK())) {
       close(0);
-      xopen_stdio(FLAG(o) ? "/dev/tty" : "/dev/null", O_RDONLY);
+      xopen_stdio(FLAG(o) ? "/dev/tty" : "/dev/null", O_RDONLY|O_CLOEXEC);
       xexec(out);
     }
     TT.np++;
diff --git a/www/design.html b/www/design.html
index 014437c..7d59f66 100644
--- a/www/design.html
+++ b/www/design.html
@@ -401,7 +401,7 @@
 <b><h3>Standards</h3></b>
 
 <p>Toybox is implemented with reference to
-<a href=http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf>c99</a>,
+<a href=https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf>c11</a>,
 <a href=roadmap.html#susv4>Posix 2008</a>,
 <a href=#bits>LP64</a>,
 <a href=roadmap.html#sigh>LSB 4.1</a>,
@@ -446,16 +446,22 @@
 using the Current Working Directory),
 but the 2013 and 2018 releases of posix were basically typo fixes: still
 release 7, still SUSv4. (An eventual release 8 might be interesting but
-it's not out yet.) We use C99 instead of C11 or newer because the new stuff
-was mostly about threading (atomic variables and such), and except for using
-// style single line comments we're more or less writing C89 code anyway.
-The main other new thing of interest in C99 was explicit width data
-types (uint32_t and friends), which LP64 handles for us.</p>
+it's not out yet.)</p>
+
+<p>We're nominally C11 but mostly just writing good old ANSI C (I.E. C89).
+We use a few of the new features like compound literals (6.5.2.5) and structure
+initialization by member name with unnamed members zeroed (6.7.9),
+but mostly we "officially" went from c99 to C11 to work around a
+<a href=https://github.com/landley/toybox/commit/3625a260065b>clang compiler bug</a>.
+The main thing we use from c99 that c89 hadn't had was // single line comments.
+(We mostly don't even use C99's explicit width data types, ala uint32_t and
+friends, because LP64 handles that for us.)</p>
 
 <p>We're ignoring new versions of the Linux Foundation's standards (LSB, FHS)
 entirely, for the same reason Debian is: they're not good at maintaining
 standards. (The Linux Foundation acquiring the Free Standards Group worked
-out about as well as Microsoft buying Nokia.)</p>
+out about as well as Microsoft buying Nokia, Twitter buying Vine, Yahoo
+buying Flickr...)</p>
 
 <p>We refer to current versions of man7.org because it's
 not easily versioned (the website updates regularly) and because
@@ -674,7 +680,7 @@
 but there should be some for the same reason writing has paragraph breaks.)</p>
 
 <p>Variable declarations go at the start of blocks, with a blank line between
-them and other code. Yes, c99 allows you to put them anywhere, but they're
+them and other code. Yes, c99 allowed you to put them anywhere, but they're
 harder to find if you do that. If there's a large enough distance between
 the declaration and the code using it to make you uncomfortable, maybe the
 function's too big, or is there an if statement or something you can
diff --git a/www/downloads/binaries/mkroot/README b/www/downloads/binaries/mkroot/README
new file mode 100644
index 0000000..8435422
--- /dev/null
+++ b/www/downloads/binaries/mkroot/README
@@ -0,0 +1,10 @@
+Bootable system images created by scripts/mkroot.sh:
+
+  LINUX=~/linux CROSS=allnonstop scripts/mkroot.sh
+
+Each system image is built from two packages: toybox and Linux.
+Run the ./qemu-*.sh script in the 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.
+
+See https://landley.net/toybox/FAQ.html#mkroot for details.
diff --git a/www/downloads/binaries/toolchains/README b/www/downloads/binaries/toolchains/README
new file mode 100644
index 0000000..869abbd
--- /dev/null
+++ b/www/downloads/binaries/toolchains/README
@@ -0,0 +1,8 @@
+These toolchains were built with musl-cross-make.tar.xz, which includes
+all the source tarballs. Run ./mcm-buildall.sh to reproduce them in the
+"ccc" subdirectory. See https://landley.net/toybox/faq.html#cross2
+for details.
+
+The native-compiler.sqf files are loopback mountable squashfs filesystems.
+
+Currently built from: musl 1.2.3, linux 5.17, gcc 9.4.0, binutils 2.33.1
diff --git a/www/faq.html b/www/faq.html
index e6fa616..d166bad 100755
--- a/www/faq.html
+++ b/www/faq.html
@@ -26,6 +26,7 @@
 <!-- get binaries -->
 <li><h2><a href="#install">How do I install toybox?</h2></li>
 <li><h2><a href="#cross">How do I cross compile toybox?</h2></li>
+<li><h2><a href="#targets">What architectures does toybox support?</li>
 <li><h2><a href="#system">What part of Linux/Android does toybox provide?</h2></li>
 <li><h2><a href="#mkroot">How do I build a working Linux system with toybox?</a></h2></li>
 </ul>
@@ -71,7 +72,7 @@
 <a href=https://www.osnews.com/story/24572/apple-ditches-samba-in-favour-of-homegrown-replacement/>new SMB server</a> from scratch to
 <a href=https://archive.org/details/copyleftconf2020-allison>replace samba</a>,
 switching <a href=https://www.theverge.com/2019/6/4/18651872/apple-macos-catalina-zsh-bash-shell-replacement-features>bash with zsh</a>, and so on.
-Toybox itself exists because somebody with in a legacy position
+Toybox itself exists because somebody in a legacy position
 just wouldn't shut up about GPLv3, otherwise I would probably
 still happily be maintaining BusyBox. (For more on how I wound
 up working on busybox in the first place,
@@ -351,8 +352,7 @@
 and is not a Google employee so does not have access
 to the Google build cluster of powerful machines capable of running the full
 AOSP build in a reasonable amount of time. Rob is working to get android
-building under android (the list of
-toybox tools Android's build uses is
+building under android (the list of toybox tools Android's build uses is
 <a href=https://android.googlesource.com/platform/prebuilts/build-tools/+/refs/heads/master/path/linux-x86/>here</a>,
 and what else it needs from its build environment is
 <a href=https://android.googlesource.com/platform/build/soong/+/refs/heads/master/ui/build/paths/config.go>here</a>), and he hopes someday to not only make a usable development
@@ -521,14 +521,67 @@
 <hr /><h2><a name="cross" />Q: How do I cross compile toybox?</h2>
 
 <p>A: You need a compiler "toolchain" capable of producing binaries that
-run on your target. A toolchain is an
+run on your target. A <a href=https://landley.net/toybox/downloads/binaries/toolchains>toolchain</a> is an
 integrated suite of compiler, assembler, and linker, plus the standard
 headers and
 libraries necessary to build C programs. (And a few miscellaneous binaries like
-nm and objdump.)</p>
+nm and objdump that display info about <a href=https://en.wikipedia.org/wiki/Executable_and_Linkable_Format>ELF files</a>.)</p>
 
-<p>Toybox is tested against two compilers (llvm, gcc) and three C libraries
-(bionic, musl, glibc) in the following combinations:</p>
+<p>Toybox supports the standard $CROSS_COMPILE prefix environnment variable,
+same as the Linux kernel build uses. This is used to prefix all the tools
+(target-cc, target-ld, target-strip) during the build, meaning the prefix
+usually ends with a "-" that's easy to forget but kind of important
+("target-cc" and "targetcc" are not the same name).</p>
+
+<p>You can either provide a
+full path in the CROSS_COMPILE string, or add the appropriate bin directory
+to your $PATH. I.E:</p>
+
+<blockquote>
+<b><p>make LDFLAGS=--static CROSS_COMPILE=~/musl-cross-make/ccc/m68k-linux-musl-cross/bin/m68k-linux-musl- distclean defconfig toybox</p></b>
+</blockquote>
+
+<p>Is equivalent to:</p>
+
+<blockquote><b><p>
+export "PATH=~/musl-cross-make/ccc/m68k-linux-musl-cross/bin:$PATH"<br />
+LDFLAGS=--static CROSS_COMPILE=m68k-linux-musl- make distclean defconfig toybox
+</p></b></blockquote>
+
+<p>Both of those examples use static linking so you can install just
+the single file to target, or test them with "qemu-m68k toybox". Feel free
+to dynamically link instead if you prefer, mkroot offers a "dynamic"
+add-on to copy the compiler's shared libraries into the new root
+filesystem.</p>
+
+<p>Although you can individually override $CC and $STRIP and such,
+providing the prefix twice applies it twice, ala
+"CROSS_COMPILE=prefix- CC=prefix-cc" gives "prefix-prefix-cc".</p>
+
+<p>Toybox's <a href=#mkroot>system builder</a> can use a simpler $CROSS
+variable to specify the target name(s) to build for if you've installed
+<a href=#cross2>compatible</a> cross compilers under the "ccc" directory.
+Behind the scenes this uses wildcard expansion to set $CROSS_COMPILE to
+an appropriate "path/prefix-".</p>
+
+<hr /><h2><a name="targets">Q: What architectures does toybox support?</h2>
+
+<p>Toybox runs on 64 bit and 32 bit processors, little endian and big endian,
+tries to respect alignment, and will enable nommu support when fork() is
+unavailable (or when TOYBOX_FORCE_NOMMU is enabled in the config to
+work around broken nommu toolchains), but otherwise tries to be
+processor agnostic (although some commands such as strace can't avoid
+a processor-specific if/else staircase.).</p>
+
+<P>Several commands (such as ps/top) are unavoidably full of Linux assumptions.
+Some subset of the commands have been made to run on BSD and MacOS X, and
+lib/portability.* and scripts/genconfig.sh exist to catch some known
+variations.</p>
+</p>
+
+<p>Each release gets tested against two compilers (llvm, gcc), three C
+libraries (bionic, musl, glibc), and a half-dozen different processor
+types, in the following combinations:</p>
 
 <a name="cross1" />
 <p><a href="#cross1">1) gcc+glibc = host toolchain</a></p>
@@ -554,15 +607,15 @@
 These days glibc is <a href=https://blog.aurel32.net/175>maintained
 by a committee</a> instead of a single
 maintainer, if that's an improvement. (As with Windows and
-Cobol, most people deal with it and get on with their lives.)</p>
+Cobol, most people just try to get on with their lives.)</p>
 
 <a name="cross2" />
 <p><a href="#cross2">2) gcc+musl = musl-cross-make</a></p>
 
-<p>The cross compilers I test this with are built from the
+<p>These cross compilers are built from the
 <a href=http://musl.libc.org/>musl-libc</a> maintainer's
 <a href=https://github.com/richfelker/musl-cross-make>musl-cross-make</a>
-project, built by running toybox's scripts/mcm-buildall.sh in that directory,
+project, built by running toybox's <a href=https://github.com/landley/toybox/blob/master/scripts/mcm-buildall.sh>scripts/mcm-buildall.sh</a> in that directory,
 and then symlink the resulting "ccc" subdirectory into toybox where
 "make root CROSS=" can find them, ala:</p>
 
@@ -575,7 +628,14 @@
 ln -s $(realpath ccc) ../toybox/ccc
 </pre></b></blockquote>
 
-<p>Instead of symlinking ccc, you can specify a CROSS_COMPILE= prefix
+<p>Since this takes a long time to run, and builds lots of targets
+(cross and native), we've uploaded
+<a href=downloads/binaries/toolchains/latest>the resulting binaries</a>
+so you can wget and extract a tarball or two instead of
+compiling them all yourself. (See the README in that directory for details.
+Yes there's a big source tarball in there for license compliance reasons.)</p>
+
+<p>Instead of CROSS= you can also specify a CROSS_COMPILE= prefix
 in the same format the Linux kernel build uses. You can either provide a
 full path in the CROSS_COMPILE string, or add the appropriate bin directory
 to your $PATH. I.E:</p>
@@ -591,14 +651,14 @@
 LDFLAGS=--static make distclean defconfig toybox CROSS=m68k-linux-musl-
 </p></b></blockquote>
 
-<p>Note: these examples use static linking becausae a dynamic musl binary
+<p>Note: these examples use static linking because a dynamic musl binary
 won't run on your host unless you install musl's libc.so into the system
 libraries (which is an accident waiting to happen adding a second C library
 to most glibc linux distribution) or play with $LD_LIBRARY_PATH.
-In theory you could "make root" a dynamic root filesystem with musl by copying
-the shared libraries out of the toolchain, but I haven't bothered implementing
-that in mkroot yet because a static linked musl hello world is 10k on x86
-(5k if stripped).</p>
+(The <a href=https://github.com/landley/toybox/blob/master/scripts/root/dynamic>dynamic</a> package
+in mkroot copies the shared libraries out of the toolchain to create a dynamic
+linking environment in the root filesystem, but it's not nearly as well
+tested.)</p>
 
 <a name="cross3" />
 <p><a href="#cross3">3) llvm+bionic = Android NDK</a></p>
@@ -661,7 +721,9 @@
 Booting a simple system to a shell prompt requires a kernel to drive the hardware (such as Linux, or BSD with a Linux emulation layer), programs for the system to run (such as toybox's commands), and a C library ("libc") to connect them together.</p>
 
 <p>Toybox has a policy of requiring no external dependencies other than the
-kernel and C library (at least for defconfig builds). You can optionally enable support for
+kernel and C library (at least for defconfig builds). Our "software bill
+of materials" (SBOM) defaults to just "the C library", both at build time
+and and runtime. You can optionally enable support for
 additional libraries in menuconfig (such as openssl, zlib, or selinux),
 but toybox either provides its own built-in versions of such functionality
 (which the libraries provide larger, more complex, often assembly optimized
@@ -697,16 +759,20 @@
 
 <hr /><h2><a name="mkroot" />Q: How do you build a working Linux system with toybox?</h2>
 
-<p>A: Toybox has a built-in <a href=https://github.com/landley/toybox/blob/master/scripts/mkroot.sh>system builder</a>, with the Makefile target "<b>make
+<p>A: Toybox has a built-in <a href=https://github.com/landley/toybox/blob/master/mkroot/mkroot.sh>system builder</a> called "<a href=https://github.com/landley/toybox/blob/master/mkroot/README>mkroot</a>", with the Makefile target "<b>make
 root</b>". To enter the resulting root filesystem, "<b>sudo chroot
 root/host/fs /init</b>". Type "exit" to get back out.</p>
 
-<p>You can cross compile simple three package (toybox+libc+linux)
-systems configured to boot to a shell prompt under the emulator
-<a href=https://qemu.org>qemu</a>
-by specifying a target type with CROSS=
-(or by setting CROSS_COMPILE= to a <a href=#cross>cross compiler</a> prefix with optional absolute
-path), and pointing the build at a Linux kernel source directory, ala:</p>
+<p>Prebuilt binary versions of these system images, suitable for running
+under the emulator <a href=https://qemu.org>qemu</a>, are uploaded to
+<a href=https://landley.net/toybox/downloads/binaries/mkroot/>the website</a>
+each release if you'd like to try before building from source.</p>
+
+<p>You can cross compile simple three package (toybox+libc+linux) systems
+configured to boot to a shell prompt under qemu by setting CROSS_COMPILE= to a
+<a href=#cross>cross compiler</a> prefix (or by installing cross compilers
+in the "ccc" subdirectory and specifying a target type with CROSS=)
+and also pointing the build at a Linux kernel source directory, ala:</p>
 
 <blockquote><p><b>make root CROSS=sh4 LINUX=~/linux</b></p></blockquote>
 
@@ -722,14 +788,19 @@
 compiler has a libc built into it, 3) you tell it where to find a Linux kernel
 source directory with LINUX= on the command line. If you don't say LINUX=,
 it skips that part of the build and just produces a root filesystem directory
-ala the first example in this FAQ answer.</p>
+(root/$CROSS/fs or root/host/fs if no $CROSS target specified), which you
+can chroot into if your architecture can run those binaries. (For PID other
+than 1, the /init script at the top of the directory sets up and cleans up
+the /proc mount points, so <b>chroot root/i686/fs /init</b> is a reasonable
+"poke around and look at things" smoketest.)</p>
 
 <p>The CROSS= shortcut expects a "ccc" symlink in the toybox source directory
-pointing at a directory full of cross compilers. The ones I test this with are built from the musl-libc
-maintainer's
+pointing at a directory full of cross compilers. The ones I test this with are
+built from the musl-libc maintainer's
 <a href=https://github.com/richfelker/musl-cross-make>musl-cross-make</a>
-project, built by running toybox's scripts/mcm-buildall.sh in that directory,
-and then symlink the resulting "ccc" subdirectory into toybox where CROSS=
+project, built by running toybox's
+<a href=https://github.com/landley/toybox/blob/master/scripts/mcm-buildall.sh>scripts/mcm-buildall.sh</a> in a musl-cross-make checkout directory,
+and then symlinking the resulting "ccc" subdirectory into toybox where CROSS=
 can find them:</p>
 
 <blockquote><b><pre>
@@ -741,8 +812,8 @@
 ln -s $(realpath ccc) ../toybox/ccc
 </pre></b></blockquote>
 
-<p>If you don't want to do that, you can download <a href=http://mkroot.musl.cc/latest/>prebuilt binary versions</a> from Zach van Rijn's site and
-just extract them into a "ccc" subdirectory under the toybox source.</p>
+<p>If you don't want to do that, you can download <a href=http://landley.net/toybox/downloads/binaries/toolchains/latest>prebuilt binary versions</a>
+and extract them into a "ccc" subdirectory under the toybox source.</p>
 
 <p>Once you've installed the cross compilers, "<b>make root CROSS=help</b>"
 should list all the available cross compilers it recognizes under ccc,
@@ -761,7 +832,7 @@
 the command line:</p>
 
 <blockquote>
-<p><b>scripts/mkroot.sh CROSS=all LINUX=~/linux dropbear</b></p>
+<p><b>mkroot/mkroot.sh CROSS=all LINUX=~/linux dropbear</b></p>
 </blockquote>
 
 <p>An example package build script (building the dropbear ssh server, adding a
diff --git a/www/git/index.html b/www/git/index.html
deleted file mode 100644
index bade8d1..0000000
--- a/www/git/index.html
+++ /dev/null
@@ -1 +0,0 @@
-Not browseable: <b>git clone https://landley.net/toybox/git</b>
diff --git a/www/header.html b/www/header.html
index 4acc95a..922fe3e 100644
--- a/www/header.html
+++ b/www/header.html
@@ -14,6 +14,7 @@
       - <a href="status.html">Status</a><br>
       - <a href="help.html">Help</a><br>
       - <a href="faq.html">FAQ</a></br>
+      - <a href="https://www.youtube.com/channel/UC4VFy3wc1nzq5tUHhiti6fw">Youtube</a></br>
     </li>
 
     <li>Why is it?<br>
@@ -28,23 +29,27 @@
           <li><a href=https://landley.net/toybox/git>local</a></li>
       </ul>
     </li>
-    <li><a href="downloads">Releases</a></li>
+    <li><a href="downloads">Source tarballs</a></li>
     <li><a href="bin">Binaries</a></li>
+    <li><a href="downloads/binaries/mkroot/latest">System Images</a></li>
+    <li><a href="downloads/binaries/toolchains/latest">Compilers</a></li>
   </ul>
-  <b>Development</b>
+  <b>Development docs</b>
   <ul>
     <li><a href="design.html">Design goals</a></li>
     <li><a href="code.html">Source code walkthrough</a></li>
+    <li><a href="cleanup.html">Cleanup</a></li>
+    <li><a href="conduct.html">Code of Conduct</a></li>
+    <li><a href="license.html">License</a></li>
+    <li><a href=https://www.openhub.net/p/toybox-landley>Statistics</a></li>
+  </ul>
+  <b>Contact</b>
+  <ul>
     <li><a href="http://lists.landley.net/listinfo.cgi/toybox-landley.net">Mailing List</a></li>
-    <ul>
-      <li>(<a href="https://www.mail-archive.com/toybox@lists.landley.net">mirror</a>)</li>
-    </ul>
     <li>IRC #toybox on libera.chat</li>
     <li><a href=https://github.com/landley/toybox/commits/master.atom>Commit RSS feed</a></li>
     <li><a href="/notes.html">Maintainer's Blog</a></li>
-    <li><a href=cleanup.html>Cleanup</a></li>
-    <li><a href=https://www.openhub.net/p/toybox-landley>Statistics</a></li>
-    <li><a href=conduct.html>Code of Conduct</a></li>
+    <li><a href="https://patreon.com/landley">Patreon</a></li>
   </ul>
 </td>
 
diff --git a/www/news.html b/www/news.html
index cc85450..c109c7b 100644
--- a/www/news.html
+++ b/www/news.html
@@ -8,6 +8,608 @@
 
 <h2>News</h2>
 
+<a name="10-01-2023" /><a href="#10-01-2023"><hr><h2><b>January 10, 2023</b></h2></a>
+<blockquote>
+<p>"Why," Arthur said, "is there a sofa in that field?"</br>
+"I told you!" shouted Ford, leaping to his feet. "Eddies in the space-time
+continuum!"</br>
+"And this is his sofa, is it?"</p>
+<p>- The Hitchhiker's Guide to the Galaxy</p>
+</p></blockquote>
+
+<p><a href=downloads/toybox-0.8.9.tar.gz>Toybox 0.8.9</a>
+(<a href=https://github.com/landley/toybox/releases/tag/0.8.9>git commit</a>)
+is out, with prebuilt <a href=downloads/binaries/0.8.9>static binaries</a> and
+<a href=downloads/binaries/mkroot/0.8.9>mkroot images</a>
+bootable under QEMU (built using a <a href=https://github.com/landley/linux/tree/mkroot-6.1>lightly patched</a> linux-6.1).</p>
+
+<p>The new <b>nbd-server</b> command interoperates with nbd-client to serve
+network block devices (using the v1 protocol), and Moritz Weber contributed a read-only <b>git</b>
+implementation to pending.</p>
+
+<p><u>Features</u>: New <b>grep</b> fast path for fixed or simple patterns that
+don't need the full regex engine (I.E. "^", ".", "$" but not "*" or "[]")
+most noticeable when searching for many patterns at once.
+Improved <b>tar --xform</b> support parsing flags= and trailing s/// scope
+flags (but using --xform now requires toybox sed in the $PATH).</p>
+
+<p>Added <b>sort -C</b>, <b>lsusb -i</b>, <b>netcat -n</b>,
+<b>swapoff -a -v</b>, <b>httpd -v</b>, <b>nbd-client -b</b>,
+a <b>uname -p</b> stub to mollify package builds,
+<b>sleep</b> accepts multiple arguments,
+<b>sed</b> now parses interlaced -e and -f arguments in order,
+several new options in <b>readlink</b> and <b>realpath</b> (and better
+handling of relative paths), and UDP mode in netcat is more useful now:
+<b>netcat -u -s 127.0.0.1 -p 9876 -l</b> can type at <b>netcat -u 127.0.0.1 9876</b>
+in both directions. (Figuring out when the other side hangs up is an unsolved
+problem, but that's UDP for you.)
+Elliott added <b>ls -N</b>.</p>
+
+<p><u>Bugfixes</u>: Fixed off by one error in <b>sort -c</b> output,
+fixed <b>sed -z</b> and other sed cases where Linux has never obeyed
+Posix (N at EOF does a default print, l escapes \n),
+<b>patch --dry-run</b> should no longer create or delete files,
+<b>gzip</b>/<b>zcat</b> couldn't handle concatenated archives,
+the ./configure of gmake 4.3 depends on <b>test</b> treating one argument -a as a synonym for -e,
+autodetectiong compression types in <b>tar</b> should be more reliable now
+and sanitize weird path corner cases (like .. past /) better,
+<b>scripts/make.sh</b> (and thus "make toybox") should no longer truncate log
+files stderr is redirected to,
+<b>httpd</b> now handles ? and # in URLs,
+<b>xxd</b> disables columns for -c 0 and groups for -g 0 (so you can get
+a long interrupted string of hex digits out of it), two fixes to
+<b>mountpoint</b> (the conversion to same_file() was inappropriate because
+the logic isn't quite the same, and -q should also quiet "not found" errors),
+fixed <b>httpd</b> not always displaying index.html files instead of directory
+contents, fixed <b>comm -</b> not recognizing it as stdin, and multiple fixes to
+<b>timeout</b> which now kills process group and thus child processes,
+isn't suspended by SIGTTIN, and recursive commands it calls don't
+inherit an inappropriate SIGCHLD handler.</p>
+
+<p>Yi-Yo Chiang fixed loopback <b>mount</b> (the recent switch to xrunread()
+kept the newline from losetup's output) and added <b>tail +123</b>
+(old-style synonym for tail -n +123).
+Daniel Mentz added scmversion to the <b>modinfo</b> tag list (Android uses
+it for external modules). Alexander Holler fixed <b>su</b> to not require
+/etc/shadow when run as root, and nomas2000 reported an inverted test in
+<b>date</b>'s check for trailing rubbish. Daniel Mentz fixed an off by
+one in <b>grep -f</b> that discarded the last character of the pattern file's
+contents. Kelvin Zhang made <b>modinfo</b> better at handling symlinks.
+Antoni Villalonga fixed <b>fmt</b> on 64 bit big endian systems (like s390x and
+powerpc). Li Cheng fixed <b>mount</b>'s type detection not autodetecting
+the need to bind mount files when type "none" was specified in fstab.
+Tomasz Sterna reported that <b>modprobe</b> resolving dependencies shouldn't
+feed a NULL pointer to the syscall's options arguments (the kernel goes -EWTF),
+and Vincent Donnefort made modprobe work when /proc/modules isn't available.</p>
+
+<p><u>Library</u>:
+The TOYFLAG_ARGFAIL() exit value is now the default <b>error_msg()</b> sets,
+<b>sendfile()</b> now falls back to the read/write loop for any error (not just
+EINVAL, the kernel sends ENOSYS and EXDEV and who knows what else),
+<b>xgetrandom()</b> can now return arbitrary amounts of data (looping internally
+as necessary),
+<b>xwaitpid()</b> returns status 127 for cases (like bad PID) which don't
+return a status for the PID,
+several fixes to <b>xabspath()</b> as part of the readlink/realpath work,
+new <b>octal_deslash()</b> to remove octal escapes common in kernel strings
+(ala /proc/mounts),
+the <b>FLAG_x</b> macros always use a 64 bit type now (so you don't have to
+worry about toys.optflags &= ~FLAG_x; blanking the top 32 bits),
+replaced memcmp() with new library function <b>smemcmp()</b> to placate ASAN
+when returning first difference in known differing arguments of unequal length.
+Elliott added three more filesystem types to <b>fs_type_name()</b> which is
+used by <b>stat -f</b> and friends.</p>
+
+<p><u>Mkroot</u>:
+New <b>scripts/test_mkroot.sh</b> runs each target under qemu to confirm
+1) it boots, 2) the block device works, 3) networking works, and 4) the clock is set
+reasonably. It runs them in parallel, with an httpd instance on the host to
+fetch a file from, and a timeout to detect hangs.
+New <b>scripts/root/overlay</b> package copies $OVERLAY directory into
+target filesystem, ala <b>scripts/mkroot.sh overlay OVERLAY=$PWD/blah</b>
+The init script now mounts any /dev/?da on /mnt and when /mnt/init exists
+sets $HANDOFF to that instead of running a shell prompt, so you can provide
+automated control images that run code in the emulator automatically. (The
+emulator process still when whatever $HANDOFF called exits.)</p>
+
+<p>Some kernel changes finally made it upstream so we can drop workarounds
+for them, such as kernel commit
+<a href=https://github.com/torvalds/linux/commit/f8f0d06438e5>f8f0d06438e5</a>
+fixing the <a href=https://landley.net/notes-2014.html#13-08-2014>longstanding</a>
+"allnoconfig has =y" issue so miniconfig doesn't need to add a magic #comment
+line forcing a symbol OFF anymore. The remaining kernel patches (including
+several maintained locally but hadn't merged into mkroot) moved to a
+<a href=https://github.com/landley/linux/tree/mkroot-6.1>seperate repository</a>
+so mkroot.sh doesn't have to call sed on the build snapshot. (They're are also
+included in the mkroot binary release directory, and were all submitted to lkml
+months if not years ago.)</p>
+
+<p>The host airlock setup (creating the temporary restricted environment
+mkroot builds packages in both so they don't pick up strange dependencies from
+the host, and to prove the build can use the toybox commands)
+removed a bunch of commands (dd, diff, vi, xzcat, ar, nm) no longer
+needed by the linux-6.1 build. The kernel patches also remove the need
+for gcc (it can use the "cc" symlink all modern distros install, and
+autodetects whether that points to gcc or clang) and bc (which is just
+<a href=https://landley.net/notes-2013.html#18-05-2013>generally obsolete</a>).
+Left those two in for one more release, but NEXT time building a vanilla
+kernel without the <a href=https://landley.net/toybox/downloads/binaries/mkroot/0.8.9/linux-patches/0001-try-generic-compiler-name-cc-before-falling-back-to-.patch>gcc removal patch</a>
+and <a href=https://landley.net/toybox/downloads/binaries/mkroot/0.8.9/linux-patches/0004-Replace-timeconst.bc-with-mktimeconst.c.patch>bc removal patch</a>
+may require you to add <b>HOST_EXTRA="gcc bc"</b> to the mkroot command line
+for the airlock build to add extra symlinks to root/build/airlock.</p>
+
+<p>Added a kernel build for powerpc64 big endian,
+m68k and powerpc now support "run-qemu.sh -hda file.img", and m68k only
+has one /dev/?db (disabled Apple Desktop Bus in the config).
+Added basic module support (the kernel build saves modules in modules.cpio.gz
+so it can extract them when you rebuild the root filesystem but not the kernel)
+and added <b>scripts/root/tests</b> which (among other things) builds two
+innocuous modules that depend on each other (fscache and cachefiles) for
+modprobe/insmod testing that hopefully won't break anything else. (If
+there was a scripts/root/pending/ tests would be in it: it does not actually
+run the test suite under mkroot yet, because toysh needs work.)</p>
+
+<p><u>Pending</u>: Elliott made <b>strace</b> build on 32-bit x86.
+James Farrell added <b>diff -f</b>.
+Alexander Holler fixed two parameter substitution bugs in <b>toysh</b>.
+Rob fixed assignment suppression, &amp;&amp; and || parsing, math
+priority, a number of ASAN test failures, untangled and commented the
+brace expansion logic, and other ongoing shell work.</p>
+
+<p>A large rewrite of diff happened but couldn't be checked in unfinished
+because if people are using stuff out of pending, how do you do a pending for
+pending? (Meta-pending?)</p>
+
+<p><u>Cleanup</u>:
+<b>cksum</b>, <b>od</b>, <b>file</b>, <b>getopt</b>, <b>gpiod</b>,
+<b>nbd-client</b>, better output messages for <b>host</b>,
+and make <b>base64</b> use line buffering.
+Moved -Wno-string-plus-int into portability.sh and had it only apply to
+clang. Moved num_cache() out of lib into netstat (its only user).</p>
+
+<p>In the test suite plumbing, $SKIPNEXT was replaced by <b>$SKIP</b> holding
+a count that counts down with each test (so you can easily skip a block of
+tests). Fixed <b>txpect</b> to actually listen to error code (oops) and to not
+complain about multiple X. The old dochroot() and mkchroot() shell functions were removed from
+scripts/runtest.sh because they required root access to use (which mkroot
+does not). More conversion to use <b>testcmd</b> in individual command.tests
+(both to remove workarounds for shell builtins, and to be more concise).
+Remove redundant cleanup from several tests (which run as proper child processes
+now, and the work directory is deleted and recreated between each, so
+individual tests need less cleanup).</p>
+
+<p><u>Portability</u>: More tests now pass on MacOS and FreeBSD
+(weird filesystems, root vs wheel group name, dealing with headers that
+define stdin as a macro and don't define PATH_MAX, the ancient bash in MacOS
+doesn't understand &amp;&gt;&gt;, won't let normal users use "chmod +s",
+symlinks don't have all permission bits set, no O_PATH and the Linux definition
+is used for something else, and so on), at least half of which Elliott did.
+Not sure we've quite got Mac and BSD
+doing "gmake test_singlecommand" right yet, but it's a lot closer.
+Added all the commands to <b>make bsd_defconfig</b> that compile on FreeBSD 13
+(which is no guarantee they WORK).
+ASAN=1 should work in more places  now, including <b>make_test_command</b>.
+The build uses $CC insted of cc in more places, and doesn't apply $ASAN
+for $HOSTCC (the legacy kconfig/ directory stands no chance).</p>
+
+Fedora inexplicably sticks \x09 style hex escapes into the dmesg output and
+expects them to be parsed.
+Android is still running the test suite under mksh which doesn't
+understand bashisms like &lt;(command). LLVM insisted that "ptr - 1" could
+never be NULL (demonstrably untrue) and needed some (unsigned long) typecasts
+to force it to actually do the math.
+Khem Raj aliased timer_settime to timer_settime64 when the first isn't
+available. Antoni Villalonga debianized some install paths and added
+a bunch of --longopt synonyms for existing options that package builds
+use.</p>
+
+<p><u>Documentation</u>: The <a href=help.html>help page</a>
+generation logic (toybox help -av) now filter out invisible aliases and
+outputs "See command" for visible aliases, plus fixes for broken corner
+cases like <b>nohup --help</b>.
+The <a href=https://landley.net/toybox/git>local git repo</a>
+now has a simple index.html generated by a
+<a href=https://github.com/landley/toybox/blob/0.8.9/scripts/git-static-index.sh>small shell script</a>,
+linking to the <b>git format-patch</b> files for
+each commit, applicable via <b>git am</b>.</p>
+
+<p>There was a
+<a href=https://github.com/landley/toybox/pull/244>bug report</a> that specifying the cross compiler prefix twice
+includes the prefix twice (ala CROSS_COMPILE=prefix- CC=prefix-cc results in
+prefix-prefix-cc) which is what happens when you ask it to do that, yes. It's now
+<a href=faq.html#cross>better documented</a>. (See also
+<a href=https://lkml.iu.edu/hypermail/linux/kernel/2202.0/01505.html>this kernel patch</a>.)</p>
+
+<p>Yi-Yo Chiang's losetup fix spawned an email thread where the
+android developers <a href=http://lists.landley.net/pipermail/toybox-landley.net/2022-August/029139.html>explained</a> why Android doesn't (and can't)
+use devtmpfs. Rob forwarded a link to linux weekly news to see if he could get
+any attention from the kernel guys, but they didn't reply.</p>
+
+<a name="12-08-2022" /><a href="#12-08-2022"><hr><h2><b>August 12, 2022</b></h2></a>
+<blockquote><p>
+Huge as office blocks, silent as birds. They hung in the air exactly the same
+way that bricks don't.</p>
+<p>- The Hitchhiker's Guide to the Galaxy</p>
+</p></blockquote>
+
+<p><a href=downloads/toybox-0.8.8.tar.gz>Toybox 0.8.8</a>
+(<a href=https://github.com/landley/toybox/releases/tag/0.8.8>git commit</a>)
+is out, with prebuilt <a href=downloads/binaries/0.8.8>static binaries</a> and
+<a href=downloads/binaries/mkroot/0.8.8>mkroot images</a>
+bootable under QEMU (built using vanilla linux-5.19).</p>
+
+<p>No new or promoted commands this time. (Time based releases mean NOT
+holding the release to wait for things like that.)</p>
+
+<p>Thanks to Google for sponsoring the project's maintainer to focus on toybox
+for a while. (They want a hermetic build, I want Android to build under
+Android. Working on it...)</p>
+
+<p><u>Features</u>:
+The new <b>timeout -i</b> option kills a command for inactivity (output
+to stdout resets the timer).
+Basic support for <b>tar --xform</b> (but not yet the special tar-only s///x
+options).
+--long options now support unambigous abbrevations by default, so you can
+go "ls --col" and it'll figure out you mean --color.
+Added <b>blkid -o</b> understanding "full", "value", and "export" output
+formats. Added <b>nsenter -C</b> (cgroup namespace) and <b>-a</b> (enable all
+supported namespaces).
+Added <b>mount -R</b> and switched the bind mount default to be recursive
+(it still autodetects --bind and --loop mounts based on the source/target type,
+all --bind or --rbind do is switch the recursive flag on and off).</p>
+
+<p>Elliott implemented <b>tar --null</b>,
+and taught <b>file</b> to recognize some Linux kernel images, and
+binaries for Linux's <a href=https://github.com/torvalds/linux/commit/fa96b57c1490>newly merged</a>
+arch/loongarch (a <a href=https://linleygroup.com/newsletters/newsletter_detail.php?num=4623>mips64 variant</a>
+from <a href=https://phoronix.com/news/LoongArch-MIPS-Copy-Kernel>china</a>).</p>
+
+<p><u>Bugfixes</u>:
+Several cleanups to taskset, mostly due to reviewing it before making
+an explainer video, but the review found an inappropriate use of
+TOYFLAG_STAYROOT that got fixed.
+Argument parsing for <b>unshare</b> and <b>nsenter</b> should now match
+debian's (I.E. "unshare -npu" works the same as "unshare -n -p -u" not
+"unshare --net=pu").
+<b>kill 1</b> no longer says "unknown pid 1: not permitted" (it
+says "bad pid" like everywhere else).
+<b>test -x</b> and friends now test live access, not permission bits.
+(Root ignores a lot of permissions, chmod u-x blocks you from executing your
+own file even if g+x and o+x should let you access it, things like selinux can
+further break the unix permission model, etc).
+
+<p>In lib/ a fencepost error in <b>chomp()</b> could read one byte past the start of the string, and
+<b>xpclose_both()</b> no longer closes the parent's stdin and stdout
+when they're explicitly passed through to the child.
+In scripts/runtest.sh, moving tests into subshells broke failure reporting with VERBOSE=all.
+While "make install" was creating directories when $PREFIX pointed to a
+nonexistent directory, "make toybox" didn't even though it tried to place the
+output file there.</p>
+
+<p>James Farrell switched the test suite from detecting root via $UID to
+$(id -u). (It's not a security issue, this just controls which tests we attempt.
+It's another workaround for missing features in mksh.)
+Taolaw spotted that httpd could segfault when xabspath() returns NULL
+(for error conditions such as infinitely looping symlinks
+or "." not resolving when the current directory was deleted).</p>
+
+<p><u>Documentation</u>:
+We <a href=design.html>recorded</a> the
+move from C99 to the C11 standard, which was actually made a while ago:
+the typecast constants we've
+been using for a while are a 2011 feature not available in the 1999 edition
+of the C standard. (This came up when we had to move to C11's "_Noreturn" to work around a compiler bug in llvm.
+Yes __attribute__((__noreturn__)) should be identical, that's the bug part.)</p>
+
+<p>The website's nav bar got updated (among other things, linking to
+our <a href=https://www.youtube.com/channel/UC4VFy3wc1nzq5tUHhiti6fw>youtube
+channel</a>), and the FAQ entry on cross compiling got
+expanded.
+The toys/example commands moved from "make list" to "make list_example"
+(since they're not enabled in defconfig either).
+The cross compiling example command line in "make help" now sets
+LDFLAGS=--static instead of putting that in CFLAGS.</p>
+
+<p>The web archive is back, and since the missing messages were
+never delivered (the mailserver trying to deliver them timed out and bounced
+them back after a couple days) this means unlike previous failures the web
+archive isn't out of sync with reality: the hole was the list actually being
+down until Dreamhost tech support figured out what they broke this time.</p>
+
+<p><u>Pending</u>:
+More work on toysh: case/esac was confused by nested flow control blocks,
+support for [[ &lt; &gt; =~ ]] tests, implemented the rest of the $((math))
+operators and support for ((math)) tests and "for ((math;math;math))" loops,
+and so on. (The next toysh goal is to get the test suite running under mkroot, but
+other stuff keeps coming up.)
+James Farrell upgraded diff, adding three line format options and support
+for diffing FIFOs.
+Rob did several rounds of dd cleanup, then got distracted by diff cleanup
+which turned into a complete rewrite of diff.
+Neither was ready to promote in time for this release though (although the release
+got delayed almost a week before Rob admitted that).</p>
+
+<p><u>Library</u>:
+The <b>lib/args.c</b> command line parser now has two optional modifiers
+(" " and ";") for each argument type, providing 4 combinations (both unset,
+both set, one of each set), and all 4 now have defined semantics and
+tests/skeleton.test exercises them. (This was motivated by <b>unshare</b>
+needing a new combination to match the debian behavior.)
+<b>lib/args.c</b> also added "~" to collate bare longopts (so multiple bare
+longopts can be synonyms setting the same flag or argument variable).</p>
+
+<p>New function <b>xrunread()</b> which launches a child function, writes a
+string to its stdin, and returns everything the child wrote to stdout as another
+string (or NULL if it couldn't run or exited with an error), leaving
+stderr alone (so it goes to the same place the parent's goes).</p>
+
+<p>New functions <b>same_file()</b> and <b>same_def_ino()</b> to simplify
+file metadata comparisons. (If you're wondering why something so simple should
+have a function encapsulating the logic, this release also has at least 3
+different bugfix commits for thinkos from switching all the commands over
+to use them instead of doing the test ourselves. All missing/extra ! or
+&& vs || level stuff.)</p>
+
+<p>The <b>exit_signal()</b> handler now blocks signals so <b>sigatexit()</b> won't
+re-enter the list when it receives two different killer signals. (Since
+<b>xexit()</b> capture uses siglongjmp() this should clean itself up
+when not actually exiting.)</p>
+
+<p><u>Plumbing</u>:
+Several warning suppressions due to things like llvm's fortify finding
+false positives, gcc's "int and long are identical on 32 bits!" warnings
+(yes... they are), the MacOS build being crotchety about vfork()... All verified
+non-issues at present.</p>
+
+<p>The build plumbing now puts more effort into resolving dependencies and figuring
+out when stuff needs to be rebuilt. This includes noticing when the
+toolchain we're building with changes flags, and outputting a warning
+when it detects the need to run "make oldconfig" again. (At the moment
+calling kconfig/ from scripts/ would be a layering violation: I need to
+rewrite kconfig from scratch before it can do that automatically.).</p>
+
+<p>Removed most compile time probes from <b>scripts/genconfig.sh</b>,
+replaced with things like #ifdef (_NR_syscall) and
+#if __has_include(&lt;utmpx.h&gt;), or acknowledging when a probe is a bug
+workaround for a specific libc version and testing for that instead,
+plus simply deleting some config options due to the 7 year horizon expiring
+so we can trust it to be there now.</p>
+
+<p>Usual batch of musl workarounds for behavior that
+<a href=https://github.com/landley/toybox/commit/9a5d7a063c8c>doesn't match</a>
+glibc and bionic or where they've been
+<a href=https://www.openwall.com/lists/musl/2022/07/27/5>arguing about</a>
+stuff for years without actually fixing it.
+Ed Maste of FreeBSD added some FreeBSD checks/cases to
+lib/portability.[hc], mostly in places we already supported Apple or
+OpenBSD.
+The top level "configure" is now re-entrant (shouldn't append stuff
+to enviornment varibles like $CFLAGS twice when read twice).
+The MacOS defconfig now includes a lot more commands.</p>
+
+<p><u>Test suite</u>:
+The diff for failing tests is now output after the FAIL line instead
+of before, "make tests" now runs tar.test by default,
+a new skeleton.test uses toys/example/skeleton.c to exercise the
+lib/args.c command line parsing plumbing,
+scripts/runtest.sh now uses do_pass and do_fail consistently,
+and Rob keeps accidentally checking in bashisms and Elliott keeps submitting
+patches to remove them because android runs the tests under mksh and
+toysh isn't ready yet.</p>
+
+<p>Work in progress to make TEST_HOST=1 pass on newer debian, which is a moving
+target. (The tests didn't change, but the behavior of the gnu utilities
+is not consistent. Or standardized. Or coherent. Or predictable. Or sane.)
+Some minor changes to commands like <b>xxd</b> and <b>cmp</b> to
+make their output look more like what debian's currently producing.</p>
+
+<p>Making the tests pass on MacOS is harder: that calls group 0 "wheel"
+instead of "root" (so things like "tar.test" don't get the same result),
+stuff like "du" or "ls" often cares what filesystem you're mounted on
+(and MacOS hasn't even got the same ones _available_), 
+and we even found a mac kernel bug where extending a sparse
+file sparsely allocates the previous length as actual zeroed disk space
+(ala "truncate -s 3m file; truncate -s 5m file; du file" says it's using
+3 megabytes of disk space). There's probably more but
+that's where we stopped looking for now: since Rob doesn't have a mac
+to test on and the github tests don't reliably run when new commits are
+pushed (skipped when the servers are busy), fixing this hasn't
+been a priority. Lots of little red X in the github history because of this,
+though...</p>
+
+<p><u>Mkroot</u>:
+The output file names are now consistent across architectures: each
+root/$TARGET directory now contains an <b>fs</b> subdirectory with the
+expanded root filesystem, packaged into <b>initramfs.cpio.gz</b>,
+a <b>linux-kernel</b> built from <b>linux-fullconfig</b> which is built
+from <b>linux-miniconfig</b>, and a <b>run-qemu.sh</b> script to launch
+it under qemu. No more architecture name in the filenames (that's what
+the directory name is for), and no more "bzImage" or "vmlinux" depending
+on what filename the kernel build produced.</p>
+
+<p>The fs/init script has better chroot support (not warning about /dev/shm and
+/dev/pts already existing).
+The airlock build no longer includes ftpd (you can use
+httpd and wget, scp out of dropbear, mount a network filesystem from the
+host, or if you really want to still use ftp can match ftpget and ftpput).
+When mkroot is downloading extra packages (for example in the dropbear build),
+it falls back to the host wget if it can't fetch with toybox's version.
+(This is because toybox hasn't got built-in https support yet, it's on the
+todo list.)
+Updated the dropbear build to the current version and fixed a compiler
+path issue.
+Fixed version skew in the <a href=http://lkml.iu.edu/hypermail/linux/kernel/2110.3/00278.html>workaround</a>
+so the Linux kernel build doesn't require a third ELF package (but only
+for x86, not for any other architecture).</p>
+
+<a name="23-07-2022" /><a href="#23-07-2022"><hr><h2><b>July 23, 2022</b></h2></a>
+<p>Sorry the mailing list has been down since the 19th, Dreamhost
+<a href=https://landley.net/notes-2022.html#22-07-2022>happened
+again</a>. (First the web archive was empty, then it was down, then it was
+restored from a backup taken before the "upgrade" but was not updating with
+new messages, which they denied was an actual problem but now timeout bounce
+messages from all the attempts to send to it since it broke have started
+coming back saying a path doesn't exist on their server...)</p>
+
+<p>Dreamhost tech support has been informed of the issue a half-dozen times,
+and did at least replace the "Currently there are no messages" page with a
+backup from before they broke it on the first day. Unfortunately they have yet
+to acknowledge anything else is wrong with it since then, and don't seem to
+have support staff working over the weekend. This used to be an
+<a href=https://landley.net/dreamhost.txt>annual</a>
+<a href=https://landley.net/dreamhost2.txt>event</a> for them,
+but they hadn't done a truly major breakage in
+<a href=#12-21-2015>a while</a>. I _think_ the 11 month gap that last link
+mentions is still missing, but the server's down again (or at least timing
+out) so I can't check.</p>
+</span>
+
+<a name="06-05-2022" /><a href="#06-05-2022"><hr><h2><b>May 6, 2022</b></h2></a>
+<blockquote><p>
+The mighty ships tore across the empty wastes of space and
+finally dived screaming on to the first planet they came across - which
+happened to be the Earth - where due to a terrible miscalculation of scale
+the entire battle fleet was accidentally swallowed by a small dog.</p>
+<p>- The Hitchhiker's Guide to the Galaxy</p></blockquote>
+
+<p><a href=downloads/toybox-0.8.7.tar.gz>Toybox 0.8.7</a>
+(<a href=https://github.com/landley/toybox/releases/tag/0.8.7>git commit</a>)
+is out, with prebuilt <a href=downloads/binaries/0.8.7>static binaries</a> and
+<a href=downloads/binaries/mkroot/0.8.7>mkroot images</a>
+bootable under QEMU (using vanilla linux-5.17).</p>
+
+<p>Rob also <a href=downloads/binaries/toolchains/latest>uploaded</a>
+the prebuilt binary cross and native compilers used to build those
+mkroot images (there's a <a href=downloads/binaries/toolchains/latest/README>README</a>
+in there), and started producing
+<a href=https://www.youtube.com/channel/UC4VFy3wc1nzq5tUHhiti6fw>tutorial videos</a> explaining the
+toybox commands, their implementation, toybox's infrastructure...</p>
+
+<p>The commands <b>host</b>, <b>wget</b>, <b>openvt</b>, and
+<b>deallocvt</b> were cleaned up and promoted.
+Elliott contributed the new commands <b>uclampset</b>, <b>gpiodetect</b>,
+<b>gpioinfo</b>, <b>gpioiget</b>, <b>gpiofind</b>, and <b>gpioset</b>,
+and Rob wrote a simple <b>httpd</b> (largely to give wget.test something to
+talk to).</p>
+
+<p>One command was removed: <b>catv</b> didn't really serve a purpose
+(everybody just uses <b>cat -v</b>).</p>
+
+
+
+
+<p><u>Features</u>:
+<b>top</b> can now move the list with the LEFT/RIGHT cursor keys (changing the
+sort field is now SHIFT LEFT/RIGHT). Added <b>find -samefile</b>,
+<b>cmp -n</b> (and wired up skip1 skip2),
+<b>tar --strip components</b> (and tar --owner and --group can now specify :UID and :GID making tar.test more portable),
+<b>lsusb</b> and </b>lspci</b> now read /etc/{usb,pci}.ids[.gz] (when
+available) to provide human readable device descriptions,
+<b>ifconfig</b> can now rename interfaces.
+Moritz Weber added <b>wget</b> post support for form data.
+In toysh, <b>cd</b> got updated ("cd -" jumps to $OLDPWD,
+and cd can now handle deleted directories).</p>
+
+<p><u>Bugfixes</u>:
+<b>cp --preserve xattr,context</b> work together now, and
+Dario Freni fixed <b>cp --xattr</b> to avoid copying selinux context.
+The <b>sort -u</b> option now implies -s, <b>wget -O -</b> now writes to stdout,
+<b>pwget -B</b> removes more characters other implementations don't emit,
+</b>time</b>'s realtime output was not properly zero padding the fractional
+part, and <b>sed</b> now works with multiple w to the same file.
+Fixed <b>nl -E</b>, <b>realpath -e</b>, <b>find</b> -newerXY and @time.nanosecond parsing,
+Various <b>sh</b> (it handles ${X: -1:1} properly now,
+which is not the same as ${X:-1:1} because :- has special meaning).
+The <b>hello</b> command in the examples directory now wait for a keypress before
+exiting when run as PID 1 (because calling wait() returned "No child process"
+immediately.)
+The multiplexer's <b>toybox command --help</b> once again shows the command's
+help (not toybox --help).
+Elliott fixed a strip bug in the MacOS build, taught <b>file</b> not to be confused
+by ELF BSS sections but to otherwise detect more invalid ELF files,
+and fixed an <b>xargs</b> bug where stdin was inappropriately O_CLOEXEC.
+Github user hg42 reported a bug where <b>tar</b> was looping trying to remove ".."
+at the start of names.</p>
+
+<p><u>Library</u>:
+Taught flags.h to #define its own CLEANUP macros so switching FLAG()
+contexts requires fewer steps.
+When args.c is just enforcing max/min argument count but collecting no
+options, imply "?" so "command -123" isn't an unknown option.
+Moved lib/help.c into main.c (nothing else in lib/ had to rebuild
+when the config changes which commands are enabled).
+The remains of linestack.c were renamed utf8.c, and
+toys.h now includes sys/syscall.h so commands don't have to.</p>
+
+<p>Yank things with only one remaining user: moved get_line()
+to patch.c, struct str_len to bc.c, and struct ptr_len to ps.c
+Removed tty_esc() and tty_jump() wrappers.
+Various cleanups to lib/password.c and lib/tty.c.
+Removed the PEDANTIC_ARGS config option which just set a macro that was never
+used, xsignal_all_killers() now takes SIG_DFL as the reset value instead
+of explicitly checking for NULL,
+chomp() now removes any number of trailing \r\n, and it's now safe to
+llist_pop(0) just like dlist_pop(0).
+LongPing Wei improved support for copy_file_range().</p>
+
+<p><u>Build</u>:
+If you don't set $PREFIX, <b>make install</b> now defaults to $PWD/install
+(which does not require root access to write to, and you can tar up your
+pile of symlinks from there).
+More command sub-options removed (NETCAT_LISTEN and CAT_V).</p>
+
+<p>Some of the uglier scripts/make.sh plumbing moved into scripts/portability.sh
+(which should now be safe to source twice),
+and moved almost all config varible definitions to "configure" now. The
+new $GENDIR variable theoretically lets the "generated" directory live
+somewhere else (not very tested yet).
+Various tweaks to scripts/make.sh to try to avoid unnecessary rebuilds
+and library probes when toolchain and config haven't changed.
+Added -Wno-pointer-sign to $CFLAGS because passing an unsigned char * to a
+function that expects char * is not a problem.
+
+<p>The airlock install in scripts/install.sh had the $PENDING items sorted
+into "started" and "not started". Add git and bash to $PENDING (used
+out of $PATH by --version and the powerpc64le build, respectively).</p>
+
+<p><u>Cleanup</u>:
+Removed the lib/linestack.c plumbing (which was never finished and hadn't
+been touched in years).
+Merged lspci.c into lsusb.c (so they can share config file reading
+infrastructure), and merged chvt/deallocvt into openvt.c.
+Minor cleanups to ping, fsync, ionice, pmap, truncate, timeout, tty,
+factor, mount.
+Went through and replaced \033 with \e in strings (since clang supports
+it and \033 is just awkward). Added LL to constant 0 in the FLAG macros
+to prevent gcc from warning that 0<<32 might produce 0.
+Moved llvm's -Wno-string-plus-int into configure instead of probing
+for it, since gcc no longer dies when asked to suppress an unknown warning.</p>
+
+<p><u>mkroot</u>:
+the ANSI escape to undo QEMU's wordwrap bug is now in both the init script
+and launch wrapper script (so wordwrap isn't broken while running the
+emulated system, nor if the emulated system fails to run).
+If devtmpfs was already mounted on /dev, we still need to create dev/pts.
+The init script now includes the linux kernel bug workaround to enable ping
+support. The armv7 target enabled CONFIG_ARM_LPAE in the kernel to work around
+around <a href=https://bugs.launchpad.net/qemu/+bug/1790975>a QEMU bug</a>
+that's gone unfixed for 4 years. Enable network support in m68k target.
+The mcm-buildall.sh script got some minor updates, and the resulting
+cross and native compiler binaries are now downloadable so you don't have
+to run the build if you don't want to.</p>
+
+<p><u>Docs</u>:
+"toybox --help" no longer says "see toybox --help".
+There's an ANSI escape cheat sheet at the start of lib/tty.c.
+Reworded some command directory READMEs, and tweaked menuconfig display.
+Converted www/doc/mount.html and www/doc/ext2.html from text to html.
+Freshened up design.html a little (and fixed some typos pointed out by
+Peter Ennis).
+Replaced the git internals video URL in roadmap.html with a different
+performance of the same talk that hasn't been made private.
+Added the kconfig-language.txt from Linux-2.6.12 to the kconfig/ directory.</p>
+
 <a name="30-11-2021" /><a href="#30-11-2021"><hr><h2><b>November 30, 2021</b></h2></a>
 <blockquote><p>
 Busy? We'll I've just got this bulldozer to lie in front of or otherwise it'll
diff --git a/www/roadmap.html b/www/roadmap.html
index 551eb2e..7c32b2a 100644
--- a/www/roadmap.html
+++ b/www/roadmap.html
@@ -131,14 +131,15 @@
 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 outside of toybox's
-mandate and should be supplied externally. (Again, some of these may be
+iconv lex m4 make nm strings strip tsort 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>
 
 <p>Some commands are part of a command shell, and can't be implemented as
 separate executables (alias bg cd command fc fg getopts hash jobs kill read
-type ulimit umask unalias wait). These may be revisited as part of the built-in
-toybox shell, but are not exported into $PATH via symlinks. (If you fork a
+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,
 for, case, export, set, unset, trap, exec... (And for bash compatibility
@@ -147,10 +148,10 @@
 <p>A few other commands are judgement calls, providing command-line
 internationalization support (iconv locale localedef), System V inter-process
 communication (ipcrm ipcs), and cross-tty communication from the minicomputer
-days (talk mesg write).  The "pax" utility <a href=https://slashdot.org/story/06/09/04/1335226/debian-kicks-jrg-schilling>failed</a> to replace tar,
+days (talk mesg write). The "pax" utility <a href=https://slashdot.org/story/06/09/04/1335226/debian-kicks-jrg-schilling>failed</a> to replace tar,
 "mailx" is
 a command line email client, and "lp" submits files for printing to... what
-exactly?  (cups?)  The standard defines crontab but not crond. What is
+exactly? (cups?) The standard defines crontab but not crond. What is
 pathchk supposed to be portable _to_? (Linux accepts 255 byte path components
 with any char except NUL or / and no max length on the total path, and
 <a href=https://yarchive.net/comp/linux/utf8.html>EXPLICITLY</a>
@@ -191,17 +192,17 @@
 
 <p>The <a href=https://mjg59.dreamwidth.org/39546.html>community perception</a>
 seems to be that the Linux Standard Base is
-the best standard money can buy, I.E. the Linux Foundation is supported by
+the best standard money can buy: the Linux Foundation is supported by
 financial donations from large companies and the LSB
 <a href=https://www.softwarefreedom.org/blog/2016/apr/11/lf/>represents the interests
 of those donors</a> regardless of technical merit. (The Linux Foundation, which
-maintains the LSB, isn't a 501c3. It's a 501c6, the
+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
 <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 affect Debian derivatives like Ubuntu and Knoppix). Toybox has
+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>
 
@@ -268,24 +269,25 @@
 <p>The RFCs are more about protocols than commands. The noise level is
 extremely high: there's thousands of RFCs, many describing a proposed idea
 that never took off, and less than 1% of the resulting documents are
-currently relevant to toybox. And the documents are numbered based on the
+currently relevant to toybox. The documents are numbered based on the
 order they were received, with no real attempt at coherently indexing
 the result. As with man pages they can be <a href=https://www.ietf.org/rfc/rfc0610.txt>long and complicated</a> or
 <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.</p>
+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>
 
 <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.c or toys/example/hello.c depending on how much
-plumbing you want to start with) provide point to posix, lsb, man, and
-rfc pages.</p>
+for new commands (toys/example/{skeleton,hello}.c) provide point to posix, lsb,
+man, and rfc pages.</p>
 
 <hr />
 <a name="dev_env">
 <h2><a href="#dev_env">Use case: provide a self-hosting development environment</a></h2>
 
-<p>The following commands were enough to build the <a href=http://landley.net/aboriginal/about.html>Aboriginal Linux</a> development
+<p>Once upon a time, the following commands were enough to build the <a href=http://landley.net/aboriginal/about.html>Aboriginal Linux</a> development
 environment, boot it to a shell prompt, and build <a href=http://www.linuxfromscratch.org/lfs/view/6.8/>Linux From Scratch 6.8</a> under it.</p>
 
 <blockquote><b>
@@ -297,7 +299,7 @@
 mkdir mktemp mv od readlink rm sed sh tail tar touch tr uniq
 wget whoami xargs chgrp comm gunzip less logname split
 tee test time bunzip2 chgrp chroot comm cpio dmesg
-dnsdomainname ftpd ftpget ftpput gunzip ifconfig init less
+dnsdomainname ftpget ftpput gunzip ifconfig init less
 logname losetup mdev mount mountpoint nc pgrep pkill 
 pwd route split stat switch_root tac umount vi
 resize2fs tune2fs fsck.ext2 genext2fs mke2fs xzcat
@@ -317,42 +319,43 @@
 To replace that toysh needs to supply several bash extensions _and_ work
 when called under the name "bash".</p>
 
-<p>The development methodology used a <a href=http://landley.net/aboriginal/FAQ.html#debug_logging>command logging wrapper</a>
-that intercepted each command called out of the $PATH and append the
-command line to a log file, then <a href=https://github.com/landley/aboriginal/blob/master/more/report-recorded-commands.sh>analyze</a> the result to create a
-<a href=https://landley.net/notes-2008.html#23-01-2008>list of commands</a>,
-then <a href=https://github.com/landley/aboriginal/blob/master/host-tools.sh>create a directory of symlinks</a> pointing to those commands out of the
-host $PATH. Then the new implementation can replace these commands one
-at a time, checking the results and the log output to spot any behavior
-changes.</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
+<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>
 
 <h3>Stages and moving targets</h3>
 
-<p>This use case has two stages: 1) building a bootable system that can
-rebuild itself from source, and 2) a build environment capable
-of bootstrapping up to arbitrary complexity (as exemplified by building
+<p>The development environment use case has two stages, achieving:
+1) a bootable system that can rebuild itself from source, and 2)
+a build environment capable
+of bootstrapping up to arbitrary complexity (by building
 Linux From Scratch and Beyond Linux From Scratch under the resulting
-system). To accomplish just the first goal, the old build
-still needs the following busybox commands for which toybox does not yet
-supply adequate replacements:</p>
+system, or the Android Open Source Project). To accomplish just the first
+goal (a minimal system that can rebuild _itself_ from source), the old
+build still needs the following busybox commands for which toybox does
+not yet supply adequate replacements:</p>
 
 <blockquote><b>
-awk dd diff expr fdisk ftpd gzip less route sh tr unxz vi wget xzcat
+awk dd diff expr fdisk gzip less route sh tr unxz vi xzcat
 </b></blockquote>
 
-<p>All of those except awk, ftpd, and less have partial implementations
+<p>All of those except awk and less have partial implementations
 in "pending".</p>
 
-<p>In 2017 Aboriginal Linux development ended, replaced by the
-<a href=https://github.com/landley/mkroot>mkroot</a> project
-designed to use an existing cross+native toolchain (such as
+<p>In 2017 Aboriginal Linux development ended, replaced by a much simpler
+project ("mkroot") designed to use an existing cross+native toolchain (such as
 <a href=https://github.com/richfelker/musl-cross-make>musl-cross-make</a>
-or the Android NDK) instead of building its own. In 2019 the still-incomplete
-mkroot was merged into toybox as the "make root" target. This is intended
+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
 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 now includes building musl-cross-make under either mkroot
-or toybox's "make airlock" host environment).</p>
+from source" test should now include building musl-cross-make under either
+mkroot or toybox's "make airlock" host environment).</p>
 
 <p>Building Linux From Scratch is not the same as building the
 <a href=https://source.android.com>Android Open Source Project</a>,
@@ -485,37 +488,36 @@
 hostname id jar java javap ln ls lsof m4 make md5sum mkdir mktemp mv od openssl
 paste patch pgrep pkill ps pstree pwd python python2.7 python3 readlink
 realpath rm rmdir rsync sed setsid sh sha1sum sha256sum sha512sum
-sleep sort stat tar tail tee todos touch tr true uname uniq unix2dos unzip
+sleep sort stat tar tail tee touch tr true uname uniq unix2dos unzip
 wc which whoami xargs xxd xz zip zipinfo
 </b></blockquote>
 
 <p>The following are already in the tree and will be used directly:</p>
 
 <blockquote><b>
-awk bzip2 jar java javap m4 make python python2.7 python3 xz
+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>bc dd diff expr gzip lsof tar tr</code>),
+that are still in pending: <code>dd diff expr getopt gzip lsof tr</code>),
 that leaves:</p>
 
 <blockquote><b>
-bash fuser getopt git hexdump openssl pstree rsync sh todos unzip zip zipinfo
+bash dlv fuser git hexdump openssl pstree rsync sh unzip zip zipinfo
 </b></blockquote>
 
-<p>For AOSP, zip/zipinfo/unzip are likely to be libziparchive based. The
-todos callers will use unix2dos instead if it's available. git/openssl
-seem like they should just be brought in to the tree. rsync is used to
-work around a Mac <code>cp -Rf</code> bug with broken symbolic links. That
-leaves:</p>
+<p>For AOSP, zip/zipinfo/unzip are likely to be libziparchive based.
+git/openssl seem like they should just be brought in to the tree. rsync is
+used to work around a Mac <code>cp -Rf</code> bug with broken symbolic links.
+That leaves:</p>
 
 <blockquote><b>
-bash fuser getopt hexdump pstree
+bash fuser hexdump pstree
 </b></blockquote>
 
 <p>(Why are fuser and pstree used during the AOSP build? They're used for
-diagnostics if something goes wrong. So it's really just bash, getopt,
-and hexdump that are actually used to build.)</p>
+diagnostics if something goes wrong. So it's really just bash and hexdump
+that are actually used to build.)</p>
 
 <hr />
 <h2><a name=tizen /><a href="#tizen">Use case: Tizen Core</a></h2>
@@ -556,7 +558,10 @@
 
 <p>Also, tizen uses a different Linux Security Module called SMACK, so
 many of the SELinux options ala ls -Z needed smack alternatives in an
-if/else setup. (We added lib/lsm.h to abstract this.)</p>
+if/else setup. We added lib/lsm.h to abstract this, but haven't heard
+from Tizen in years and have started implementing SELinux support without
+Smack support in places like tar.c. At some point, lib/lsm.h may go away
+due to lack of expressed interest.</p>
 
 <hr />
 <h2><a name=yocto /><a href="#yocto">Use case: Yocto</a></h2>
@@ -572,11 +577,14 @@
 the layers (let alone their contents). But -- and this is the
 important bit -- all these dispirate forks are called "yocto" and built on
 top of giant piles of code the Linux Foundation can take credit for
-since they filed the serial numbers off OpenEmbedded.</p>
+since they filed the serial numbers off OpenEmbedded. (And THEN users
+are encouraged to check the result into their own repository as one
+big initial commit, discarding all layers and history.)</p>
 
 <p>Yocto's "core-image-minimal" target (only 3,106 build steps in the 3.3
-release, which believe it or not is
-<a href=https://landley.net/notes-2019.html#06-02-2019>an improvement</a>) builds a busybox-based system with the following commands:</p>
+release, which includes building host versions of gnome packages and
+<a href=https://landley.net/notes-2019.html#06-02-2019>something called</a>
+the "uninative binary shim") builds a busybox-based system with the following commands:</p>
 
 <blockquote><b>
 <span id=yocto_cmd>
@@ -668,8 +676,8 @@
 <a href=http://www.infoworld.com/d/data-center/perl-isnt-going-anywhere-better-or-worse-211580>requires perl to build</a>, and seems like an ideal candidate for
 replacement.</p>
 
-<p>In addition to a C library less general-purpose than bionic (let alone
-musl), klibc builds a random assortment of executables to run init scripts
+<p>In addition to a C library less general-purpose than old versions of bionic
+(let alone musl), klibc builds a random assortment of executables to run init scripts
 with. There's no multiplexer command, these are individual executables:</p>
 
 <blockquote><p><b>
@@ -697,7 +705,7 @@
 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
-license terms" above).
+license terms" above).</p>
 
 <p>In theory "blkid" or "file" handle fstype (and df for mounted filesystems),
 but we could do fstype.</p>
@@ -756,7 +764,7 @@
 <li><b>catchsegv</b> is a rudimentary debugger, probably out of scope for toybox.</li>
 <li><b>iconv</b> has been <a href="#susv4">previously discussed</a>.</li>
 <li><b>iconvconfig</b> is only relevant if iconv is user-configurable; musl uses a
-non-configurable iconv.</li>
+non-configurable iconv now that utf8+unicode exist.</li>
 <li><b>getconf</b> is a posix utility which displays several variables from 
 unistd.h; it probably belongs in the development toolchain.</li>
 <li><b>getent</b> handles retrieving entries from passwd-style databases
@@ -818,16 +826,15 @@
 
 <p>Plus sh because it's a shell. A dozen or so commands can only sanely be
 implemented as shell builtins (alias aliasall cd exec exit prompt quit setenv
-source umask unalias), where is an alias for which, and at triage time toybox
-already has chgrp, chmod, chown, cmp, cp, chroot, echo, help, kill, losetup,
-ln, ls, mkdir, mknod, printenv, pwd, rm, rmdir, sync, and touch.</p>
+source umask unalias), and where is an alias for which.</p>
 
 <p>This leaves:</p>
 
 <blockquote><b>
 <span id=sash_cmd>
-ar chattr dd ed file find grep gunzip gzip lsattr more mount mv pivot_root
-sh tar umount
+chgrp chmod chown cmp cp chroot echo find grep help kill losetup
+ln ls mkdir mknod mount mv pivot_root printenv pwd rm rmdir sync tar touch umount
+ar chattr dd ed file gunzip gzip lsattr more sh
 </span>
 </b></blockquote>
 
@@ -908,7 +915,7 @@
 </p></blockquote>
 
 <p>This list is nuts: "plymouth" is an alias for "null" which is basically
-"true" (which thie above list doesn't have). Things like buildEnv and
+"true" (which the above list doesn't have). Things like buildEnv and
 loadDrivers are bespoke Red Hat behavior that might as well be hardwired in
 to nash's main() without being called.</p>
 
@@ -1014,8 +1021,7 @@
 which predated iptables, which is in the process of being replaced by
 nftables.</p>
 
-<p>Nevertheless, people still try to use this because (at least until the
-launch of <a href=http://nommu.org>nommu.org</a>) the project was viewed
+<p>Nevertheless, people still try to use this because the project was viewed
 as the place to discuss, develop, and learn about nommu Linux.
 The role of uclinux.org as an educational resource kept people coming
 to it long after it had collapsed as a Linux distro.</p>
@@ -1177,7 +1183,9 @@
 their dropbear is from 2012, and that ssh version is from 2011
 (which means it's about nine months too _old_ to have the heartbleed bug).
 There's both ulogd and ulogd2 (no idea why), and pppd is version 2.4 but
-there's a ppd-2.3 directory also.</p>
+there's a ppd-2.3 directory also. We used to be interested in ftpd/proftpd
+as a way of uploading files out of a vm, but support for that has waned
+over the years and there are lots of alternatives.</p>
 
 <p>Lots of flash stuff:
 flashw is a flash writer, load is an spi flash loader, netflash writes
@@ -1191,9 +1199,9 @@
 
 <blockquote><b><p>
 agetty cal cksum cron dhcpcd dhcpcd-new dhcpd dhcp-isc dosfstools e2fsprogs
-elvis-tiny levee fdisk fileutils ftp ftpd grep hd hwclock inetd init ntp
+elvis-tiny levee fdisk fileutils ftp grep hd hwclock inetd init ntp
 iputils login module-init-tools netcat shutils ntpdate lspci ping procps
-proftpd rsync shadow shutils stty sysutils telnet telnetd tftp tftpd traceroute
+rsync shadow shutils stty sysutils telnet telnetd tftp tftpd traceroute
 unzip wget mawk net-tools
 </p></b></blockquote>
 
@@ -1242,6 +1250,7 @@
 pwgen readelf unicode
 rsync
 linux32 hd strace
+gpiodetect gpiofind gpioget gpioinfo gpioset httpd uclampset
 </span>
 </b></blockquote>
 
@@ -1262,7 +1271,7 @@
 shared libraries in its lib/ directory, it does not currently provide a shared
 library interface.)</p>
 
-<h3>Packages toybox plans to provide complete-ish replacents for:</h3>
+<h3>Packages toybox plans to provide complete-ish replacements for:</h3>
 <ul>
 <li><b>file</b>: file (see also: libmagic)</li>
 <li><b>m4</b>: [m4]</li>
@@ -1279,7 +1288,6 @@
 <li><b>less</b>: less (not: lessecho lesskey)</li>
 <li><b>gzip</b>: zcat [gzip] [gunzip] [zcmp] [zdiff] [zegrep] [zfgrep] [zgrep] [zless] [zmore]
 (not: gzexe uncompress zforce znew)</li>
-<li><b>make</b>: [make]</li>
 <li><b>patch</b>: patch</li>
 <li><b>tar</b>: tar</li>
 <li><b>procps-ng</b>: free pgrep pidof pkill ps sysctl top uptime vmstat w watch
@@ -1341,7 +1349,7 @@
 (which contains arp route ifconfig mii-tool nameif netstat and rarp that
 toybox does or might implement, and plipconfig slattach that it probably won't.)</p>
 
-<h3>Packages toybox plans to provide partial replacents for:</h3>
+<h3>Packages toybox plans to provide partial replacements for:</h3>
 
 <p>Toybox provides replacements for some binaries from these packages,
 but there are other useful binaries which this package provides that toybox