aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 01:05:51 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 01:05:51 +0000
commit4fedcd7c8efb4b361ab8643584100583d52a472e (patch)
tree5dbbb5fd7edc0e5025ee19f52aea2a52fee72b1c
parent452ee4eada8e5bb1f433edb152cc7037038548d1 (diff)
parent9323773b0b13f0b51f0874572a4a87ce40855934 (diff)
downloadtoybox-android14-mainline-cellbroadcast-release.tar.gz
Change-Id: Ib48f9d0449169a15e13d348d3959ec3a24210644
-rw-r--r--.config-device46
-rw-r--r--.config-linux38
-rw-r--r--.config-mac38
-rw-r--r--.github/workflows/toybox.yml18
-rw-r--r--Android.bp8
-rw-r--r--METADATA10
-rw-r--r--Makefile8
-rw-r--r--README8
-rw-r--r--TEST_MAPPING8
-rw-r--r--android/device/generated/config.h92
-rw-r--r--android/device/generated/flags.h2375
-rw-r--r--android/device/generated/globals.h175
-rw-r--r--android/device/generated/help.h102
-rw-r--r--android/device/generated/newtoys.h111
-rw-r--r--android/linux/generated/config.h76
-rw-r--r--android/linux/generated/flags.h1551
-rw-r--r--android/linux/generated/globals.h175
-rw-r--r--android/linux/generated/help.h100
-rw-r--r--android/linux/generated/newtoys.h111
-rw-r--r--android/mac/generated/config.h76
-rw-r--r--android/mac/generated/flags.h1445
-rw-r--r--android/mac/generated/globals.h175
-rw-r--r--android/mac/generated/help.h100
-rw-r--r--android/mac/generated/newtoys.h111
-rwxr-xr-xconfigure3
-rw-r--r--kconfig/Makefile3
-rw-r--r--kconfig/android_miniconfig198
-rw-r--r--kconfig/freebsd_miniconfig36
-rw-r--r--kconfig/lkc.h4
-rw-r--r--kconfig/macos_miniconfig104
-rw-r--r--lib/args.c221
-rw-r--r--lib/deflate.c70
-rw-r--r--lib/dirtree.c62
-rw-r--r--lib/env.c2
-rw-r--r--lib/lib.c136
-rw-r--r--lib/lib.h29
-rw-r--r--lib/llist.c29
-rw-r--r--lib/net.c46
-rw-r--r--lib/password.c2
-rw-r--r--lib/portability.c109
-rw-r--r--lib/portability.h82
-rw-r--r--lib/tty.c8
-rw-r--r--lib/xwrap.c52
-rw-r--r--main.c35
-rwxr-xr-xmkroot/mkroot.sh309
-rwxr-xr-xmkroot/record-commands (renamed from scripts/record-commands)0
-rwxr-xr-xmkroot/root/dropbear (renamed from scripts/root/dropbear)17
-rwxr-xr-xmkroot/root/dynamic15
-rwxr-xr-xmkroot/root/overlay3
-rwxr-xr-xmkroot/root/plumbing (renamed from scripts/root/plumbing)10
-rwxr-xr-xmkroot/root/tests15
-rwxr-xr-xmkroot/testroot.sh99
-rwxr-xr-xpost_update.sh4
-rwxr-xr-xrun-tests-on-android.sh6
-rwxr-xr-xscripts/change.sh10
-rwxr-xr-xscripts/genconfig.sh91
-rwxr-xr-xscripts/git-static-index.sh28
-rw-r--r--scripts/help.txt3
-rwxr-xr-xscripts/install.sh9
-rwxr-xr-xscripts/make.sh247
-rwxr-xr-xscripts/mcm-buildall.sh13
-rw-r--r--scripts/mkflags.c34
-rwxr-xr-xscripts/mkroot.sh293
-rwxr-xr-xscripts/mkstatus.py2
-rw-r--r--scripts/portability.sh22
-rw-r--r--scripts/runtest.sh224
-rwxr-xr-xscripts/single.sh10
-rwxr-xr-xscripts/test.sh20
-rw-r--r--tests/bc.test1
-rwxr-xr-xtests/blkid.test8
-rwxr-xr-xtests/chattr.test4
-rwxr-xr-xtests/chmod.test4
-rwxr-xr-xtests/cmp.test9
-rwxr-xr-xtests/comm.test7
-rwxr-xr-xtests/cpio.test54
-rwxr-xr-xtests/cut.test6
-rw-r--r--tests/date.test3
-rw-r--r--tests/diff.test102
-rwxr-xr-xtests/factor.test5
-rw-r--r--tests/files/blkid/iso.bz2bin0 -> 367 bytes
-rwxr-xr-xtests/grep.test231
-rwxr-xr-x[-rw-r--r--]tests/gunzip.test0
-rwxr-xr-xtests/head.test31
-rwxr-xr-xtests/httpd.test15
-rwxr-xr-xtests/ifconfig.test39
-rwxr-xr-xtests/ls.test108
-rw-r--r--tests/lsattr.test12
-rw-r--r--tests/modinfo.test4
-rwxr-xr-xtests/patch.test30
-rwxr-xr-xtests/printf.test86
-rwxr-xr-xtests/readlink.test11
-rwxr-xr-xtests/realpath.test65
-rwxr-xr-xtests/sed.test159
-rwxr-xr-xtests/seq.test2
-rw-r--r--tests/sh.test128
-rwxr-xr-xtests/skeleton.test45
-rwxr-xr-xtests/sort.test5
-rwxr-xr-x[-rw-r--r--]tests/tar.test391
-rw-r--r--tests/test.test64
-rwxr-xr-x[-rw-r--r--]tests/timeout.test9
-rwxr-xr-xtests/truncate.test5
-rw-r--r--tests/xargs.test2
-rwxr-xr-xtests/xxd.test60
-rwxr-xr-xtests/zcat.test20
-rw-r--r--toys.h9
-rw-r--r--toys/android/log.c16
-rw-r--r--toys/android/runcon.c2
-rw-r--r--toys/example/skeleton.c10
-rw-r--r--toys/lsb/dmesg.c13
-rw-r--r--toys/lsb/gzip.c20
-rw-r--r--toys/lsb/hostname.c2
-rw-r--r--toys/lsb/killall.c1
-rw-r--r--toys/lsb/md5sum.c9
-rw-r--r--toys/lsb/mktemp.c10
-rw-r--r--toys/lsb/mount.c65
-rw-r--r--toys/lsb/passwd.c1
-rw-r--r--toys/lsb/seq.c32
-rw-r--r--toys/lsb/su.c6
-rw-r--r--toys/lsb/umount.c2
-rw-r--r--toys/net/host.c18
-rw-r--r--toys/net/httpd.c201
-rw-r--r--toys/net/netcat.c107
-rw-r--r--toys/net/netstat.c36
-rw-r--r--toys/net/sntp.c6
-rw-r--r--toys/net/tunctl.c2
-rw-r--r--toys/net/wget.c (renamed from toys/pending/wget.c)81
-rw-r--r--toys/other/base64.c7
-rw-r--r--toys/other/blkid.c50
-rw-r--r--toys/other/devmem.c2
-rw-r--r--toys/other/factor.c38
-rw-r--r--toys/other/fmt.c2
-rw-r--r--toys/other/fsfreeze.c3
-rw-r--r--toys/other/gpiod.c7
-rw-r--r--toys/other/help.c26
-rw-r--r--toys/other/hexedit.c2
-rw-r--r--toys/other/hwclock.c6
-rw-r--r--toys/other/i2ctools.c131
-rw-r--r--toys/other/login.c16
-rw-r--r--toys/other/losetup.c10
-rw-r--r--toys/other/lsattr.c6
-rw-r--r--toys/other/lsusb.c80
-rw-r--r--toys/other/mcookie.c2
-rw-r--r--toys/other/mkswap.c2
-rw-r--r--toys/other/modinfo.c1
-rw-r--r--toys/other/mountpoint.c26
-rw-r--r--toys/other/nbd_client.c96
-rw-r--r--toys/other/nbd_server.c88
-rw-r--r--toys/other/nsenter.c86
-rw-r--r--toys/other/oneit.c33
-rw-r--r--toys/other/openvt.c2
-rw-r--r--toys/other/pmap.c8
-rw-r--r--toys/other/pwgen.c2
-rw-r--r--toys/other/readelf.c10
-rw-r--r--toys/other/readlink.c107
-rw-r--r--toys/other/sha3sum.c4
-rw-r--r--toys/other/shred.c2
-rw-r--r--toys/other/shuf.c63
-rw-r--r--toys/other/stat.c12
-rw-r--r--toys/other/swapoff.c28
-rw-r--r--toys/other/taskset.c58
-rw-r--r--toys/other/timeout.c104
-rw-r--r--toys/other/uptime.c1
-rw-r--r--toys/other/usleep.c2
-rw-r--r--toys/other/vmstat.c117
-rw-r--r--toys/other/w.c1
-rw-r--r--toys/other/watchdog.c2
-rw-r--r--toys/other/xxd.c69
-rw-r--r--toys/pending/bc.c2
-rw-r--r--toys/pending/bootchartd.c43
-rw-r--r--toys/pending/brctl.c6
-rw-r--r--toys/pending/dd.c122
-rw-r--r--toys/pending/diff.c727
-rw-r--r--toys/pending/getopt.c1
-rw-r--r--toys/pending/git.c657
-rw-r--r--toys/pending/init.c4
-rw-r--r--toys/pending/lsof.c22
-rw-r--r--toys/pending/mke2fs.c4
-rw-r--r--toys/pending/modprobe.c10
-rw-r--r--toys/pending/sh.c993
-rw-r--r--toys/pending/strace.c52
-rw-r--r--toys/pending/sulogin.c1
-rw-r--r--toys/pending/tcpsvd.c84
-rw-r--r--toys/pending/vi.c273
-rw-r--r--toys/posix/cat.c60
-rw-r--r--toys/posix/chgrp.c17
-rw-r--r--toys/posix/cksum.c30
-rw-r--r--toys/posix/cmp.c22
-rw-r--r--toys/posix/comm.c16
-rw-r--r--toys/posix/cp.c34
-rw-r--r--toys/posix/cpio.c131
-rw-r--r--toys/posix/cut.c6
-rw-r--r--toys/posix/date.c4
-rw-r--r--toys/posix/df.c4
-rw-r--r--toys/posix/du.c19
-rw-r--r--toys/posix/file.c84
-rw-r--r--toys/posix/find.c44
-rw-r--r--toys/posix/grep.c229
-rw-r--r--toys/posix/head.c7
-rw-r--r--toys/posix/iconv.c1
-rw-r--r--toys/posix/kill.c5
-rw-r--r--toys/posix/ln.c6
-rw-r--r--toys/posix/logger.c22
-rw-r--r--toys/posix/ls.c155
-rw-r--r--toys/posix/nohup.c11
-rw-r--r--toys/posix/od.c24
-rw-r--r--toys/posix/patch.c35
-rw-r--r--toys/posix/printf.c19
-rw-r--r--toys/posix/ps.c33
-rw-r--r--toys/posix/pwd.c3
-rw-r--r--toys/posix/rm.c2
-rw-r--r--toys/posix/sed.c236
-rw-r--r--toys/posix/sleep.c9
-rw-r--r--toys/posix/sort.c23
-rw-r--r--toys/posix/tail.c19
-rw-r--r--toys/posix/tar.c322
-rw-r--r--toys/posix/test.c50
-rw-r--r--toys/posix/time.c2
-rw-r--r--toys/posix/touch.c1
-rw-r--r--toys/posix/ulimit.c1
-rw-r--r--toys/posix/uname.c3
-rw-r--r--toys/posix/uuencode.c13
-rw-r--r--toys/posix/who.c1
-rw-r--r--toys/posix/xargs.c4
-rw-r--r--www/design.html22
-rw-r--r--www/downloads/binaries/mkroot/README10
-rw-r--r--www/downloads/binaries/toolchains/README8
-rwxr-xr-xwww/faq.html135
-rw-r--r--www/git/index.html1
-rw-r--r--www/header.html21
-rw-r--r--www/news.html602
-rw-r--r--www/roadmap.html154
231 files changed, 11723 insertions, 7296 deletions
diff --git a/.config-device b/.config-device
index 196378ec..c90db6d5 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_BLKDISCARD=y
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_CKSUM=y
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_DATE=y
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_GETENFORCE=y
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_GUNZIP=y
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_HELP=y
# 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_KILL=y
# 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_MKDIR_Z=y
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_MODPROBE=y
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_PATCH=y
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_SHA384SUM=y
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_SYNC=y
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_TRACEROUTE=y
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_WHICH=y
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 0a542595..73e55ac9 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_BASENAME=y
# 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_CMP=y
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_EXPR=y
# 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_GETCONF=y
# 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_GREP=y
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_HEAD=y
# 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_LN=y
# 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_MKTEMP=y
# 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_SHA256SUM=y
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_WHICH=y
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 3770579e..6ff9493a 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_BASENAME=y
# 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_CMP=y
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_EXPR=y
# 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_GETCONF=y
# 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_GREP=y
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_HEAD=y
# 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_LN=y
# 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_MKTEMP=y
# 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_SHA256SUM=y
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_WHICH=y
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 79403217..a2f06219 100644
--- a/.github/workflows/toybox.yml
+++ b/.github/workflows/toybox.yml
@@ -7,22 +7,8 @@ on:
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 a8e74913..f6a06108 100644
--- a/Android.bp
+++ b/Android.bp
@@ -98,6 +98,7 @@ all_srcs = [
"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 @@ device_srcs = [
"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 @@ device_srcs = [
"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 @@ toybox_symlinks = [
"base64",
"basename",
"blockdev",
+ "brctl",
"cal",
"cat",
"chattr",
@@ -310,6 +313,7 @@ toybox_symlinks = [
"load_policy",
"ln",
"log",
+ "logger",
"logname",
"losetup",
"ls",
@@ -406,6 +410,7 @@ toybox_symlinks = [
"uudecode",
"uuencode",
"uuidgen",
+ "vi",
"vmstat",
"watch",
"wc",
@@ -427,6 +432,7 @@ cc_defaults {
"-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 191882c0..0f8e19e8 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 @@ third_party {
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 40987027..52f0851c 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,7 @@ toybox generated/unstripped/toybox: $(KCONFIG_CONFIG) *.[ch] lib/*.[ch] toys/*/*
.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 @@ distclean: clean root_clean
@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 f39c9216..580459b9 100644
--- a/README
+++ b/README
@@ -39,12 +39,12 @@ toybox to run on the current machine. Cross compiling requires an appropriately
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 cdb49349..6e9020af 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 415d99e8..f260bf1f 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 ced393db..ef9fc67a 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
+
+// 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:46uU[!tlL][!Lw][!46U] ^tElLw#<1W#<1p#<1>65535q#<1s:f:46uU[!tlL][!Lw][!46U]
+// 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 403077b0..2b646d04 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 @@ struct skeleton_data {
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 @@ struct mktemp_data {
// 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 @@ struct tunctl_data {
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 acpi_data {
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 blkdiscard_data {
struct blkid_data {
struct arg_list *s;
+ char *o;
};
// toys/other/blockdev.c
@@ -268,7 +287,7 @@ struct fallocate_data {
// toys/other/fmt.c
struct fmt_data {
- int width;
+ long width;
int level, pos;
};
@@ -343,7 +362,7 @@ struct lsattr_data {
struct lsusb_data {
char *i;
- long n;
+ long x, n;
void *ids, *class;
int count;
@@ -384,10 +403,18 @@ struct modinfo_data {
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 @@ struct readelf_data {
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 @@ struct shred_data {
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 tac_data {
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 crontab_data {
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 @@ struct dhcpd_data {
// 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 getty_data {
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 @@ struct sh_data {
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 @@ struct sh_data {
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 @@ struct syslogd_data {
// 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 useradd_data {
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 @@ struct vi_data {
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 @@ struct vi_data {
} *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 @@ struct cp_data {
// toys/posix/cpio.c
struct cpio_data {
- char *F, *H;
+ char *F, *H, *R;
};
// toys/posix/cut.c
@@ -1320,8 +1352,8 @@ struct grep_data {
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 ln_data {
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 @@ struct ps_data {
} 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 @@ struct sed_data {
// 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 tail_data {
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 @@ extern union global_union {
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 @@ extern union global_union {
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 @@ extern union global_union {
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 @@ extern union global_union {
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 04e62120..72a74f50 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, 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_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_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] HOST PORT DEVICE\n\n-n Do not fork into background\n-s nbd swap support (lock server into memory)"
+#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 ade88313..0680e5d9 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_ARCH(NEWTOY(arch, 0, TOYFLAG_USR|TOYFLAG_BIN))
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_CHOWN(OLDTOY(chown, chgrp, TOYFLAG_BIN))
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_MANY_OPTIONS(NEWTOY(demo_many_options, "ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwv
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_SH(NEWTOY(exit, 0, TOYFLAG_NOFORK))
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_GETENFORCE(NEWTOY(getenforce, ">0", TOYFLAG_USR|TOYFLAG_SBIN))
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_HEXEDIT(NEWTOY(hexedit, "<1>1r", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
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_LOGIN(NEWTOY(login, ">1f:ph:", TOYFLAG_BIN|TOYFLAG_NEEDROOT))
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_MKTEMP(NEWTOY(mktemp, ">1(tmpdir);:uqd(directory)p:t", TOYFLAG_BIN))
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_PWDX(NEWTOY(pwdx, "<1a", TOYFLAG_USR|TOYFLAG_BIN))
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_SHA3SUM(NEWTOY(sha3sum, "bSa#<128>512=224", TOYFLAG_USR|TOYFLAG_BIN))
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_STRINGS(NEWTOY(strings, "t:an#=4<1fo", TOYFLAG_USR|TOYFLAG_BIN))
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_SYSCTL(NEWTOY(sysctl, "^neNqwpaA[!ap][!aq][!aw][+aA]", TOYFLAG_SBIN))
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_TEST(NEWTOY(test, 0, TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_NOHELP|TOYFLAG_MAYFORK)
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_UCLAMPSET(NEWTOY(uclampset, "p#am#<-1>1024M#<-1>1024R", TOYFLAG_USR|TOYFLAG_
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_VMSTAT(NEWTOY(vmstat, ">2n", TOYFLAG_BIN))
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 7d2c7302..a1d03da5 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 2ab033b6..3e550a7e 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 403077b0..2b646d04 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 @@ struct skeleton_data {
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 @@ struct mktemp_data {
// 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 @@ struct tunctl_data {
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 acpi_data {
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 blkdiscard_data {
struct blkid_data {
struct arg_list *s;
+ char *o;
};
// toys/other/blockdev.c
@@ -268,7 +287,7 @@ struct fallocate_data {
// toys/other/fmt.c
struct fmt_data {
- int width;
+ long width;
int level, pos;
};
@@ -343,7 +362,7 @@ struct lsattr_data {
struct lsusb_data {
char *i;
- long n;
+ long x, n;
void *ids, *class;
int count;
@@ -384,10 +403,18 @@ struct modinfo_data {
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 @@ struct readelf_data {
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 @@ struct shred_data {
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 tac_data {
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 crontab_data {
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 @@ struct dhcpd_data {
// 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 getty_data {
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 @@ struct sh_data {
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 @@ struct sh_data {
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 @@ struct syslogd_data {
// 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 useradd_data {
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 @@ struct vi_data {
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 @@ struct vi_data {
} *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 @@ struct cp_data {
// toys/posix/cpio.c
struct cpio_data {
- char *F, *H;
+ char *F, *H, *R;
};
// toys/posix/cut.c
@@ -1320,8 +1352,8 @@ struct grep_data {
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 ln_data {
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 @@ struct ps_data {
} 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 @@ struct sed_data {
// 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 tail_data {
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 @@ extern union global_union {
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 @@ extern union global_union {
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 @@ extern union global_union {
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 @@ extern union global_union {
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 30c24e92..aef88284 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, 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_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_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] HOST PORT DEVICE\n\n-n Do not fork into background\n-s nbd swap support (lock server into memory)"
+#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 ade88313..0680e5d9 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_ARCH(NEWTOY(arch, 0, TOYFLAG_USR|TOYFLAG_BIN))
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_CHOWN(OLDTOY(chown, chgrp, TOYFLAG_BIN))
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_MANY_OPTIONS(NEWTOY(demo_many_options, "ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwv
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_SH(NEWTOY(exit, 0, TOYFLAG_NOFORK))
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_GETENFORCE(NEWTOY(getenforce, ">0", TOYFLAG_USR|TOYFLAG_SBIN))
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_HEXEDIT(NEWTOY(hexedit, "<1>1r", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
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_LOGIN(NEWTOY(login, ">1f:ph:", TOYFLAG_BIN|TOYFLAG_NEEDROOT))
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_MKTEMP(NEWTOY(mktemp, ">1(tmpdir);:uqd(directory)p:t", TOYFLAG_BIN))
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_PWDX(NEWTOY(pwdx, "<1a", TOYFLAG_USR|TOYFLAG_BIN))
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_SHA3SUM(NEWTOY(sha3sum, "bSa#<128>512=224", TOYFLAG_USR|TOYFLAG_BIN))
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_STRINGS(NEWTOY(strings, "t:an#=4<1fo", TOYFLAG_USR|TOYFLAG_BIN))
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_SYSCTL(NEWTOY(sysctl, "^neNqwpaA[!ap][!aq][!aw][+aA]", TOYFLAG_SBIN))
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_TEST(NEWTOY(test, 0, TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_NOHELP|TOYFLAG_MAYFORK)
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_UCLAMPSET(NEWTOY(uclampset, "p#am#<-1>1024M#<-1>1024R", TOYFLAG_USR|TOYFLAG_
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_VMSTAT(NEWTOY(vmstat, ">2n", TOYFLAG_BIN))
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 a9f4bdf9..bd4c09b7 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 516ffc76..0cb1833c 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 403077b0..2b646d04 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 @@ struct skeleton_data {
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 @@ struct mktemp_data {
// 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 @@ struct tunctl_data {
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 acpi_data {
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 blkdiscard_data {
struct blkid_data {
struct arg_list *s;
+ char *o;
};
// toys/other/blockdev.c
@@ -268,7 +287,7 @@ struct fallocate_data {
// toys/other/fmt.c
struct fmt_data {
- int width;
+ long width;
int level, pos;
};
@@ -343,7 +362,7 @@ struct lsattr_data {
struct lsusb_data {
char *i;
- long n;
+ long x, n;
void *ids, *class;
int count;
@@ -384,10 +403,18 @@ struct modinfo_data {
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 @@ struct readelf_data {
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 @@ struct shred_data {
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 tac_data {
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 crontab_data {
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 @@ struct dhcpd_data {
// 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 getty_data {
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 @@ struct sh_data {
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 @@ struct sh_data {
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 @@ struct syslogd_data {
// 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 useradd_data {
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 @@ struct vi_data {
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 @@ struct vi_data {
} *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 @@ struct cp_data {
// toys/posix/cpio.c
struct cpio_data {
- char *F, *H;
+ char *F, *H, *R;
};
// toys/posix/cut.c
@@ -1320,8 +1352,8 @@ struct grep_data {
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 ln_data {
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 @@ struct ps_data {
} 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 @@ struct sed_data {
// 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 tail_data {
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 @@ extern union global_union {
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 @@ extern union global_union {
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 @@ extern union global_union {
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 @@ extern union global_union {
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 30c24e92..aef88284 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, 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_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_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] HOST PORT DEVICE\n\n-n Do not fork into background\n-s nbd swap support (lock server into memory)"
+#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 ade88313..0680e5d9 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_ARCH(NEWTOY(arch, 0, TOYFLAG_USR|TOYFLAG_BIN))
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_CHOWN(OLDTOY(chown, chgrp, TOYFLAG_BIN))
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_MANY_OPTIONS(NEWTOY(demo_many_options, "ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwv
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_SH(NEWTOY(exit, 0, TOYFLAG_NOFORK))
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_GETENFORCE(NEWTOY(getenforce, ">0", TOYFLAG_USR|TOYFLAG_SBIN))
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_HEXEDIT(NEWTOY(hexedit, "<1>1r", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
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_LOGIN(NEWTOY(login, ">1f:ph:", TOYFLAG_BIN|TOYFLAG_NEEDROOT))
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_MKTEMP(NEWTOY(mktemp, ">1(tmpdir);:uqd(directory)p:t", TOYFLAG_BIN))
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_PWDX(NEWTOY(pwdx, "<1a", TOYFLAG_USR|TOYFLAG_BIN))
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_SHA3SUM(NEWTOY(sha3sum, "bSa#<128>512=224", TOYFLAG_USR|TOYFLAG_BIN))
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_STRINGS(NEWTOY(strings, "t:an#=4<1fo", TOYFLAG_USR|TOYFLAG_BIN))
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_SYSCTL(NEWTOY(sysctl, "^neNqwpaA[!ap][!aq][!aw][+aA]", TOYFLAG_SBIN))
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_TEST(NEWTOY(test, 0, TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_NOHELP|TOYFLAG_MAYFORK)
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_UCLAMPSET(NEWTOY(uclampset, "p#am#<-1>1024M#<-1>1024R", TOYFLAG_USR|TOYFLAG_
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_VMSTAT(NEWTOY(vmstat, ">2n", TOYFLAG_BIN))
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 c718e83b..d6bbd7da 100755
--- a/configure
+++ b/configure
@@ -12,7 +12,8 @@ then
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 2e8e5dcd..3bd5f6a4 100644
--- a/kconfig/Makefile
+++ b/kconfig/Makefile
@@ -39,6 +39,8 @@ macos_defconfig: $(obj)/conf $(KCONFIG_TOP)
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 @@ help::
@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 00000000..4428a2b9
--- /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 3a6fa80a..c945aa49 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_COMM=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_GREP=y
+CONFIG_EGREP=y
+CONFIG_FGREP=y
CONFIG_HEAD=y
CONFIG_ICONV=y
CONFIG_ID=y
@@ -50,13 +53,13 @@ CONFIG_SLEEP=y
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_WHO=y
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_FLOCK=y
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_MOUNTPOINT=y
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_TRUNCATE=y
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 9b629ffa..3b31ccbd 100644
--- a/kconfig/lkc.h
+++ b/kconfig/lkc.h
@@ -152,4 +152,8 @@ static inline bool sym_has_value(struct symbol *sym)
}
#endif
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
#endif /* LKC_H */
diff --git a/kconfig/macos_miniconfig b/kconfig/macos_miniconfig
index 26c21b15..6b9f6b48 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_TIMEOUT=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_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_WATCH=y
+CONFIG_WC=y
CONFIG_WHICH=y
+CONFIG_WHO=y
+CONFIG_WHOAMI=y
+CONFIG_XARGS=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_TOYBOX_FLOAT=y
-CONFIG_TOYBOX_HELP=y
-CONFIG_TOYBOX_HELP_DASHDASH=y
+CONFIG_ZCAT=y
diff --git a/lib/args.c b/lib/args.c
index 2b8da7c7..53258279 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 @@ struct getoptflagstate
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 @@ static int gotflag(struct getoptflagstate *gof, struct opts *opt, int shrt)
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;
-
- 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"
-
- 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 = "";
+ // 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);
+
+ // 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;
+
+ 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 @@ static int parse_optflaglist(struct getoptflagstate *gof)
// 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 @@ static int parse_optflaglist(struct getoptflagstate *gof)
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 @@ static int parse_optflaglist(struct getoptflagstate *gof)
} 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 @@ static int parse_optflaglist(struct getoptflagstate *gof)
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 @@ static int parse_optflaglist(struct getoptflagstate *gof)
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 @@ void get_optflags(void)
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 @@ void get_optflags(void)
gof.arg++;
if (*gof.arg=='-') {
struct longopts *lo;
+ struct arg_list *al = 0, *al2;
+ int ii;
gof.arg++;
// Handle --
@@ -427,28 +427,51 @@ void get_optflags(void)
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 @@ void get_optflags(void)
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 @@ void get_optflags(void)
// 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 cdc4f8d3..a418c21c 100644
--- a/lib/deflate.c
+++ b/lib/deflate.c
@@ -17,7 +17,7 @@ struct deflate {
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 @@ static struct bitbuf *bitbuf_init(int fd, int size)
// 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 @@ static inline int bitbuf_bit(struct bitbuf *bb)
int bufpos = bb->bitpos>>3;
if (bufpos == bb->len) {
- bitbuf_skip(bb, 0);
+ bitbuf_skip(bb, -1);
bufpos = 0;
}
@@ -83,7 +88,10 @@ static unsigned bitbuf_get(struct bitbuf *bb, int bits)
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 unsigned huff_and_puff(struct bitbuf *bb, struct huff *huff)
static void inflate(struct deflate *dd, struct bitbuf *bb)
{
dd->crc = ~0;
+
// repeat until spanked
for (;;) {
int final, type;
@@ -322,7 +331,7 @@ static void deflate(struct deflate *dd, struct bitbuf *bb)
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 @@ static int is_gzip(struct bitbuf *bb)
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 @@ long long gunzip_fd(int infd, int outfd)
{
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 4023101e..00de64e4 100644
--- a/lib/dirtree.c
+++ b/lib/dirtree.c
@@ -52,11 +52,11 @@ struct dirtree *dirtree_add_node(struct dirtree *parent, char *name, int flags)
}
// 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 @@ error:
}
if (parent) parent->symlink = (char *)1;
free(dt);
+
return 0;
}
@@ -116,15 +117,25 @@ int dirtree_parentfd(struct dirtree *node)
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 @@ static struct dirtree *dirtree_handle_callback(struct dirtree *new,
}
// 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 facde63f..d47e8d23 100644
--- a/lib/env.c
+++ b/lib/env.c
@@ -61,7 +61,7 @@ char *xsetenv(char *name, char *val)
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 cf0a9582..c9207a99 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -17,7 +17,7 @@ void verror_msg(char *msg, int err, va_list va)
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 @@ char *strafter(char *haystack, char *needle)
// 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 @@ int strcasestart(char **a, char *b)
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 @@ void loopfiles_rw(char **argv, int flags, int permissions,
// 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 @@ void generic_signal(int sig)
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 @@ char *fileunderdir(char *file, char *dir)
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 @@ void names_to_pid(char **names, int (*callback)(pid_t pid, char *name),
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 @@ int qstrcmp(const void *a, const void *b)
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 @@ int is_tar_header(void *pkt)
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 @@ char *elf_arch_name(int type)
{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 @@ char *elf_arch_name(int type)
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 70e5bed9..6165ac11 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 @@ struct double_list {
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_lpop(void *list); // also struct double_list **list
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 @@ int xpclose_both(pid_t pid, int *pipes);
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 @@ int xopenro(char *path);
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 @@ int unescape2(char **c, int echo);
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 @@ void loggit(int priority, char *format, ...);
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 @@ int pollinate(int in1, int in2, int out1, int out2, int timeout, int shutdown_ti
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 @@ int comma_remove(char *optlist, char *opt);
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 @@ mode_t string_to_mode(char *mode_str, mode_t base);
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 6ceb1ce7..63a98bb6 100644
--- a/lib/llist.c
+++ b/lib/llist.c
@@ -116,32 +116,3 @@ void *dlist_terminate(void *list)
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 414c82a5..16a110e3 100644
--- a/lib/net.c
+++ b/lib/net.c
@@ -173,3 +173,49 @@ int xrecvwait(int fd, char *buf, int len, union socksaddr *sa, int timeout)
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 3497176a..6bea3d70 100644
--- a/lib/password.c
+++ b/lib/password.c
@@ -23,7 +23,7 @@ int get_salt(char *salt, char *algo)
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 89744dd0..a9f28154 100644
--- a/lib/portability.c
+++ b/lib/portability.c
@@ -30,20 +30,25 @@ pid_t xfork(void)
}
#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 @@ struct mtab_list *xgetmountlist(char *path)
#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 @@ struct mtab_list *xgetmountlist(char *path)
#endif
-#if defined(__APPLE__) || defined(__OpenBSD__)
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
#include <sys/event.h>
@@ -332,7 +313,7 @@ ssize_t xattr_fset(int fd, const char* name,
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 @@ int dev_minor(int dev)
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 @@ int dev_major(int dev)
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 @@ int dev_makedev(int major, int minor)
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 @@ int dev_makedev(int major, int minor)
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 @@ char *fs_type_name(struct statfs *statfs)
{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 @@ int get_block_device_size(int fd, unsigned long long* size)
*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 @@ int timer_settime(timer_t t, int flags, struct itimerspec *new, void *old)
// 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 @@ int timer_create_wrap(clockid_t c, struct sigevent *se, timer_t *t)
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 77b6a2a6..f35ce77f 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 @@ int wcwidth(wchar_t wc);
#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 @@ void *memmem(const void *haystack, size_t haystack_length,
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 @@ void *memmem(const void *haystack, size_t haystack_length,
#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 @@ int posix_fallocate(int, off_t, off_t);
#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 @@ static inline long statfs_frsize(struct statfs *sf) { return sf->f_frsize; }
// 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 @@ static inline void endutxent(void) {;}
// 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 @@ static inline void endutxent(void) {;}
#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 @@ typedef float FLOAT;
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 @@ typedef struct {char *c_name; int c_val;} CODE;
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 @@ struct itimerspec {
};
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 c09413b5..3f26976e 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 @@ int tty_fd(void)
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 65e9f4fe..5ea47d4c 100644
--- a/lib/xwrap.c
+++ b/lib/xwrap.c
@@ -251,10 +251,8 @@ pid_t xpopen_setup(char **argv, int *pipes, void (*callback)(char **argv))
// 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 @@ pid_t xpopen_both(char **argv, int *pipes)
// 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 xwaitpid(pid_t pid)
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 @@ int xrun(char **argv)
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 @@ int xdup(int fd)
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 @@ int xtempfile(char *name, char **tempname)
// 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 @@ char *xabspath(char *path, int flags)
}
// 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 9d9d7061..b4971bcd 100644
--- a/main.c
+++ b/main.c
@@ -76,26 +76,32 @@ static char *help_data =
#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 @@ void check_help(char **arg)
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 @@ void toy_singleinit(struct toy_list *which, char *argv[])
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 00000000..0447b386
--- /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
index d2b779fa..d2b779fa 100755
--- a/scripts/record-commands
+++ b/mkroot/record-commands
diff --git a/scripts/root/dropbear b/mkroot/root/dropbear
index 75839c34..9a4adcb8 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 @@ echo === download source
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 @@ CC=${CROSS_COMPILE}cc LD=${CROSS_COMPILE}ld AS=${CROSS_COMPILE}as ./configure &&
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 @@ setupfor dropbear
# 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 @@ for i in "$ROOT"/bin/{ssh,dropbear,scp,dropbearkey}
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 @@ echo 'ssh -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" ${1:+$
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 00000000..2ecfbdaa
--- /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 00000000..be0aaede
--- /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
index ff302803..e72247c0 100755
--- a/scripts/root/plumbing
+++ b/mkroot/root/plumbing
@@ -11,23 +11,23 @@ mkdir -p "${DOWNLOAD:=$PWD/root_download}" || exit 1
# 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 00000000..bca3b40c
--- /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 00000000..0e3f4494
--- /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 05c550cc..39aefde8 100755
--- a/post_update.sh
+++ b/post_update.sh
@@ -22,8 +22,12 @@ function generate() {
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 89c8c916..d641b380 100755
--- a/run-tests-on-android.sh
+++ b/run-tests-on-android.sh
@@ -65,7 +65,11 @@ test_toy() {
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 74889aa7..dda5ee14 100755
--- a/scripts/change.sh
+++ b/scripts/change.sh
@@ -9,15 +9,11 @@ ${HOSTCC:-cc} -I . scripts/install.c -o "$UNSTRIPPED"/instlist &&
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 034aa376..52a9c259 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 @@ probesymbol()
{
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 @@ EOF
#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 @@ toys()
$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 @@ do
[ "$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 00000000..fb9ac4e5
--- /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 d369e47a..feca0a8d 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 842ff9b0..38d9dcec 100755
--- a/scripts/install.sh
+++ b/scripts/install.sh
@@ -31,7 +31,6 @@ done
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 @@ done
# 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 b7bb6930..9de74192 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..."
-
-mkdir -p "$UNSTRIPPED"
-
-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
+# 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
+}
-# 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.
+# 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"/newtoys.h toys
-then
- echo -n "$GENDIR/newtoys.h "
+ # 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
+}
- 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
+# 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
-[ ! -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 @@ then
# 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
-#TODO: "make $SED && make" doesn't regenerate config.h because diff .config
-if true #isnewer "$GENDIR"/config.h "$KCONFIG_CONFIG"
+if isnewer Config.in toys || isnewer Config.in Config.in
then
- echo "Make $GENDIR/config.h from $KCONFIG_CONFIG."
+ 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 config.h "$KCONFIG_CONFIG"
+then
# 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 @@ then
$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 @@ function getglobals()
{
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 @@ then
) > "$GENDIR"/globals.h
fi
-if [ ! -f "$UNSTRIPPED"/mktags ] || [ "$UNSTRIPPED"/mktags -ot scripts/mktags.c ]
-then
- do_loudly $HOSTCC scripts/mktags.c -o "$UNSTRIPPED"/mktags || exit 1
-fi
-
-if isnewer "$GENDIR"/tags.h toys
+hostcomp mktags
+if isnewer 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 @@ do
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 @@ then
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 cac41372..11a10136 100755
--- a/scripts/mcm-buildall.sh
+++ b/scripts/mcm-buildall.sh
@@ -91,7 +91,11 @@ make_toolchain()
# 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 @@ fix_nommu()
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 6560db50..79cf1656 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 @@ int chrtype(char c)
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 @@ char *mark_gaps(char *flags, char *all)
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 @@ struct flag *digest(char *string)
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 @@ struct flag *digest(char *string)
} 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 @@ int main(int argc, char *argv[])
// 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 @@ int main(int argc, char *argv[])
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 @@ int main(int argc, char *argv[])
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 @@ int main(int argc, char *argv[])
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 c099bec7..2ac634bc 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 ed6dd544..41a1bed2 100755
--- a/scripts/mkstatus.py
+++ b/scripts/mkstatus.py
@@ -40,7 +40,7 @@ print "all commands=%s" % len(reverse)
# 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 3af2be5f..4241916a 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 @@ fi
# 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 5a647677..ce6e0fd0 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).
-
-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
+# Function "optional" enables/disables tests based on configuration options.
+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,34 +42,64 @@ then
SHOWSKIP="$(echo -e "\033[1;33m${SHOWSKIP}\033[0m")"
fi
-optional()
+# Helper functions
+
+# Check if VERBOSE= contains a given string. (This allows combining.)
+verbose_has()
{
- option=`printf %s "$OPTIONFLAGS" | egrep "(^|:)$1(:|\$)"`
- # Not set?
- if [ -z "$1" ] || [ -z "$OPTIONFLAGS" ] || [ ${#option} -ne 0 ]
+ [ "${VERBOSE/$1/}" != "$VERBOSE" ]
+}
+
+wrong_args()
+{
+ if [ $# -ne 5 ]
then
- unset SKIP
- return
+ printf "%s\n" "Test $NAME has the wrong number of arguments ($# $*)" >&2
+ exit
fi
- SKIP=1
}
-verbose_has()
+# Announce success
+do_pass()
{
- [ "${VERBOSE/$1/}" != "$VERBOSE" ]
+ verbose_has nopass || printf "%s\n" "$SHOWPASS: $NAME"
}
+# Announce failure and handle fallout for txpect
+do_fail()
+{
+ FAILCOUNT=$(($FAILCOUNT+1))
+ printf "%s\n" "$SHOWFAIL: $NAME"
+ if [ ! -z "$CASE" ]
+ then
+ echo "Expected '$CASE'"
+ echo "Got '$A'"
+ fi
+ ! 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 "$@" 2>/dev/null
+ eval "$@" >/dev/null 2>&1
else
eval "$@"
fi
- [ $? -eq 0 ] || SKIPNEXT=1
+ [ $? -eq 0 ] || { ((++SKIP)); return 1; }
}
+# Skip this test (rest of command line) when not running toybox.
toyonly()
{
IS_TOYBOX="$("$C" --version 2>/dev/null)"
@@ -93,61 +108,40 @@ toyonly()
case "$IS_TOYBOX" in
toybox*) ;;
This\ is\ not\ GNU*) ;;
- *) SKIPNEXT=1 ;;
+ *) [ $SKIP -eq 0 ] && ((++SKIP)) ;;
esac
"$@"
}
-wrong_args()
-{
- if [ $# -ne 5 ]
- then
- printf "%s\n" "Test $NAME has the wrong number of arguments ($# $*)" >&2
- exit
- fi
-}
-
-# Announce success
-do_pass()
-{
- ! verbose_has nopass && printf "%s\n" "$SHOWPASS: $NAME"
-}
-
-# The testing function
-
+# Takes five arguments: "name" "command" "result" "infile" "stdin"
testing()
{
- NAME="$CMDNAME $1"
wrong_args "$@"
- [ -z "$1" ] && NAME=$2
+ [ -z "$1" ] && NAME="$2" || NAME="$1"
+ [ "${NAME#$CMDNAME }" == "$NAME" ] && NAME="$CMDNAME $1"
[ -n "$DEBUG" ] && set -x
- if [ -n "$SKIP" -o -n "$SKIP_HOST" -a -n "$TEST_HOST" -o -n "$SKIPNEXT" ]
+ if [ "$SKIP" -gt 0 ]
then
- verbose_has quiet && printf "%s\n" "$SHOWSKIP: $NAME"
- unset SKIPNEXT
+ verbose_has quiet || printf "%s\n" "$SHOWSKIP: $NAME"
+ ((--SKIP))
+
return 0
fi
- echo -ne "$3" > expected
+ echo -ne "$3" > ../expected
[ ! -z "$4" ] && echo -ne "$4" > input || rm -f input
- echo -ne "$5" | ${EVAL:-eval --} "$2" > actual
+ echo -ne "$5" | ${EVAL:-eval --} "$2" > ../actual
RETVAL=$?
# Catch segfaults
- [ $RETVAL -gt 128 ] && [ $RETVAL -lt 255 ] &&
+ [ $RETVAL -gt 128 ] &&
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
+ 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"
@@ -156,34 +150,22 @@ testing()
fi
[ -n "$DIFF" ] && ! verbose_has all && exit 1
- rm -f input expected actual
+ 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 "$@"
- X="$1"
- [ -z "$X" ] && X="$CMDNAME $2"
- testing "$X" "\"$C\" $2" "$3" "$4" "$5"
+ testing "${1:-$CMDNAME $2}" "\"$C\" $2" "$3" "$4" "$5"
}
-# Announce failure and handle fallout for txpect
-do_fail()
-{
- FAILCOUNT=$(($FAILCOUNT+1))
- printf "%s\n" "$SHOWFAIL: $NAME"
- if [ ! -z "$CASE" ]
- then
- echo "Expected '$CASE'"
- echo "Got '$A'"
- fi
- ! verbose_has all && exit 1
-}
+# 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
@@ -191,7 +173,7 @@ do_fail()
# 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 @@ txpect()
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 @@ txpect()
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 @@ txpect()
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 023ccea6..f4f28be9 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 @@ else
# 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 @@ do
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 da22f661..c29a9aa9 100755
--- a/scripts/test.sh
+++ b/scripts/test.sh
@@ -8,26 +8,28 @@ export FILES="$PWD"/tests/files
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 @@ do_test()
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 65969b79..710b0132 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 5bfce435..bcd38f3d 100755
--- a/tests/blkid.test
+++ b/tests/blkid.test
@@ -28,6 +28,9 @@ testing "ext4" "BLKID ext4" \
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 @@ toyonly testing "stdin" "bzcat $FILES/blkid/squashfs.bz2 | blkid -" \
#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 8f1c4b2c..01549b07 100755
--- a/tests/chattr.test
+++ b/tests/chattr.test
@@ -51,7 +51,7 @@ testing "append-only" "$IN && echo "$_t" > testFile &&
# 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 @@ testing "multiple files" "$IN && touch fileA && touch fileB &&
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 6c4de0c0..97c9e939 100755
--- a/tests/chmod.test
+++ b/tests/chmod.test
@@ -104,13 +104,13 @@ chtest a-w,a+x "dr-xr-xr-x\n-r-xr-xr-x\n"
# 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 ce776e8e..9a3da335 100755
--- a/tests/cmp.test
+++ b/tests/cmp.test
@@ -22,7 +22,8 @@ c" > input2
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 "diff, return code" "input input2 > /dev/null || echo yes" "yes\n" "ab\n
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 63d9c847..2891c6b2 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 183dadde..6f5eddef 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 @@ printf '333' >dddd
# 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 @@ if [ "$(id -u)" -eq 0 ]; then
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 889fc186..c354b9b2 100755
--- a/tests/cut.test
+++ b/tests/cut.test
@@ -18,7 +18,7 @@ testcmd "-b overlaps" "-b 1-3,2-5,7-9,9-10 abc.txt" \
"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 japan.txt" '-c 3-6,9-12 "$FILES/utf8/japan.txt"' \
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 @@ Weather forecast for tonight : dark.
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 dfcefb26..9777edb3 100644
--- a/tests/date.test
+++ b/tests/date.test
@@ -97,3 +97,6 @@ testing "tz + 8 : 8 " \
# 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 f78eaa66..ddca4766 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" "" ""
+' "" ""
+mkdir -p tree1 tree2
+echo foo > tree1/file
+echo food > tree2/file
-expected='--- tree1/file
+# 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
-'
-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" "" ""
+' "" ""
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 b556c3a7..90151851 100755
--- a/tests/factor.test
+++ b/tests/factor.test
@@ -20,3 +20,8 @@ testing "10000000019" "factor 10000000019" \
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 00000000..f6babd50
--- /dev/null
+++ b/tests/files/blkid/iso.bz2
Binary files differ
diff --git a/tests/grep.test b/tests/grep.test
index dbab4cc0..c7fab92d 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" ""
-
-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 "-x" "-x abc input" "abc\n" "aabcc\nabc\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" \
- "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" \
+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 "-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"
-
-testing "-A" "grep -A 2 yes" "yes\nno\nno\n--\nyes\nno\nno\nyes\nno\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"
+
+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 @@ mkdir dir
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
index bf9b9834..bf9b9834 100644..100755
--- a/tests/gunzip.test
+++ b/tests/gunzip.test
diff --git a/tests/head.test b/tests/head.test
index 4e4c01bd..e23b70d7 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 00000000..ac07c39e
--- /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 ca8ca89e..dcecc16f 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 @@ then
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 @@ then
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 4856da5c..fad27d3b 100755
--- a/tests/ls.test
+++ b/tests/ls.test
@@ -9,64 +9,72 @@
#set -x
# Creating test-file/dir for testing ls
-mkdir -p lstest/dir1 lstest/dir2 || exit 1
-echo "test file1" > lstest/file1.txt
-echo "test file2" > lstest/file2.txt
-echo "hidden file1" > lstest/.hfile1
+mkdir -p dir1 dir2 || exit 1
+echo "test file1" > file1.txt
+echo "test file2" > file2.txt
+echo "hidden file1" > .hfile1
-IN="cd lstest"
-OUT="cd .. "
+testcmd "no argument" "" "dir1\ndir2\nfile1.txt\nfile2.txt\n" "" ""
+testcmd "-C column spacing equals 2" "-C" "dir1 dir2 file1.txt file2.txt\n" \
+ "" ""
+testcmd "-x column spacing equals 2" "-x" "dir1 dir2 file1.txt file2.txt\n" \
+ "" ""
+testcmd "explicit files" "file*" "file1.txt\nfile2.txt\n" "" ""
+testcmd "explicit -1" "-1 file*" "file1.txt\nfile2.txt\n" "" ""
+testcmd "" "-p" "dir1/\ndir2/\nfile1.txt\nfile2.txt\n" "" ""
+testcmd "" "-a" ".\n..\n.hfile1\ndir1\ndir2\nfile1.txt\nfile2.txt\n" "" ""
+testcmd "" "-A" ".hfile1\ndir1\ndir2\nfile1.txt\nfile2.txt\n" "" ""
+testcmd "" "-d" ".\n" "" ""
+testcmd "" "-d *" "dir1\ndir2\nfile1.txt\nfile2.txt\n" "" ""
+testcmd "" "-k" "dir1\ndir2\nfile1.txt\nfile2.txt\n" "" ""
+testcmd "-m" "-m" "dir1, dir2, file1.txt, file2.txt\n" "" ""
+testcmd "-F" "-F" "dir1/\ndir2/\nfile1.txt\nfile2.txt\n" "" ""
+testcmd "-dk *" "-dk *" "dir1\ndir2\nfile1.txt\nfile2.txt\n" "" ""
+testcmd "-Z" "-Z file1.txt | egrep -q '^[^ ]+ file1.txt' || echo fail" "" "" ""
+testcmd "-lZ" "--full-time -lZ file1.txt | egrep -q '^-[rwx-]+ +[0-9]+ +[^ ]+ +[^ ]+ +[^ ]+ +[0-9]+ [0-9][0-9][0-9][0-9]-[0-9][0-9]-.* file1.txt' || echo fail" "" "" ""
-testing "no argument" "$IN && ls; $OUT" "dir1\ndir2\nfile1.txt\nfile2.txt\n" "" ""
-testing "with -C: test column spacing equals 2" "$IN && ls -C; $OUT" "dir1 dir2 file1.txt file2.txt\n" "" ""
-testing "with -x: test column spacing equals 2" "$IN && ls -x; $OUT" "dir1 dir2 file1.txt file2.txt\n" "" ""
-testing "with wild char" "$IN && ls file*; $OUT" "file1.txt\nfile2.txt\n" "" ""
-testing "with wild char - long listing" "$IN && ls -1 file*; $OUT" "file1.txt\nfile2.txt\n" "" ""
-testing "with -p" "$IN && ls -p; $OUT" "dir1/\ndir2/\nfile1.txt\nfile2.txt\n" "" ""
-testing "with -a" "$IN && ls -a; $OUT" \
- ".\n..\n.hfile1\ndir1\ndir2\nfile1.txt\nfile2.txt\n" "" ""
-testing "with -A" "$IN && ls -A; $OUT" \
- ".hfile1\ndir1\ndir2\nfile1.txt\nfile2.txt\n" "" ""
-testing "with -d" "$IN && ls -d; $OUT" ".\n" "" ""
-testing "with wild char and -d *" "$IN && ls -d *; $OUT" "dir1\ndir2\nfile1.txt\nfile2.txt\n" "" ""
-testing "with -k" "$IN && ls -k; $OUT" "dir1\ndir2\nfile1.txt\nfile2.txt\n" "" ""
-testing "with -m" "$IN && ls -m; $OUT" "dir1, dir2, file1.txt, file2.txt\n" "" ""
-testing "with -F" "$IN && ls -F; $OUT" "dir1/\ndir2/\nfile1.txt\nfile2.txt\n" "" ""
-testing "with -dk *" "$IN && ls -dk *; $OUT" "dir1\ndir2\nfile1.txt\nfile2.txt\n" "" ""
-testing "with -Z" "$IN && ls -Z file1.txt | egrep -q '^[^ ]+ file1.txt' || echo fail; $OUT" "" "" ""
-testing "with -lZ" "$IN && ls --full-time -lZ file1.txt | egrep -q '^-[rwx-]+ +[0-9]+ +[^ ]+ +[^ ]+ +[^ ]+ +[0-9]+ [0-9][0-9][0-9][0-9]-[0-9][0-9]-.* file1.txt' || echo fail; $OUT" "" "" ""
+ln -s file1.txt slink
+testcmd "-l symlink" "-l slink | grep -q -- ' slink -> file1.txt' && echo ok" \
+ "ok\n" "" ""
+rm -f slink
-ln -s file1.txt lstest/slink
-testing "-l symlink" \
- "$IN && ls -l slink | grep -q -- ' slink -> file1.txt' && echo ok ; $OUT" \
- "ok\n" "" ""
-rm -f lstest/slink
+ln -s /dev/null/nosuchfile nosuchfile
+testcmd "-d broken symlink" "-d nosuchfile" "nosuchfile\n" "" ""
+rm -f nosuchfile
-ln -s /dev/null/nosuchfile lstest/nosuchfile
-testing "with -d - broken softlink" "$IN && ls -d nosuchfile; $OUT" "nosuchfile\n" "" ""
-rm -f lstest/nosuchfile
+rm -rf file{1,2}.txt .hfile dir1 dir2
-rm -rf lstest/* && mkdir -p lstest/dir1 && touch lstest/file1.txt
-testing "nested recursively" "$IN && ls -R; $OUT" \
- ".:\ndir1\nfile1.txt\n\n./dir1:\n" "" ""
+mkdir -p dir1 && touch file1.txt dir1/file2
+testcmd "" "-R" ".:\ndir1\nfile1.txt\n\n./dir1:\nfile2\n" "" ""
+rm -rf dir1 file1.txt
-rm -rf lstest/* && touch lstest/file1.txt && INODE=`stat -c %i lstest/file1.txt`
-testing "with -i" "$IN && ls -i 2>/dev/null; $OUT" "$INODE file1.txt\n" "" ""
-unset INODE
+touch file1.txt
+testcmd "-i" "-i" "$(stat -c %i file1.txt) file1.txt\n" "" ""
+testcmd "missing" "does-not-exist 2>&1 >/dev/null | grep -o does-not-exist" \
+ "does-not-exist\n" "" ""
+rm -f file1.txt
-testing "missing" "$IN && ls does-not-exist 2>&1 >/dev/null | grep -o does-not-exist; $OUT" "does-not-exist\n" "" ""
-
-rm -f lstest/{file1.txt,err}
-touch lstest/{one,two,three,four,five,six,seven,eight,nine,ten}
-testing "-w test 1" "$IN && ls -Cw 20; $OUT" \
+# sort tests
+TIME=1234567890
+for i in one two three four five six seven eight nine ten
+ do touch -d @$((TIME++)) $i
+done
+testcmd "" "-r" "two\nthree\nten\nsix\nseven\none\nnine\nfour\nfive\neight\n" \
+ "" ""
+testcmd "-w test 1" "-Cw 20" \
"eight one three\nfive seven two\nfour six\nnine ten\n" "" ""
-testing "-w test 2" "$IN && ls -Cw 19; $OUT" \
+testcmd "-w test 2" "-Cw 19" \
"eight seven\nfive six\nfour ten\nnine three\none two\n" "" ""
+rm -f one two three four five six seven eight nine ten
-rm -rf lstest/*
-touch lstest/{a,b,c,d,e,f}
-testing "-w test 3" "$IN && ls -Cw 3; $OUT" "a\nb\nc\nd\ne\nf\n" "" ""
-testing "-w test 4" "$IN && ls -Cw 4; $OUT" "a d\nb e\nc f\n" "" ""
+touch a b c d e f
+testcmd "-w test 3" "-Cw 3" "a\nb\nc\nd\ne\nf\n" "" ""
+testcmd "-w test 4" "-Cw 4" "a d\nb e\nc f\n" "" ""
+rm -f a b c d e f
-# Removing test dir for cleanup purpose
-rm -rf lstest
+touch 'hello world'
+testcmd "default escaping" "" "hello world\n" "" ""
+testcmd "-b" "-b" 'hello\\ \\rworld\n' "" ""
+testcmd "-q" "-q" 'hello ?world\n' "" ""
+testcmd "-N" "-N" 'hello world\n' "" ""
+rm hello*
diff --git a/tests/lsattr.test b/tests/lsattr.test
index 63d9ee9c..f2beef56 100644
--- a/tests/lsattr.test
+++ b/tests/lsattr.test
@@ -31,12 +31,12 @@ NOSPACE=1 testing "-v file" "lsattr -v file | clean" "_ $_A file\n" "" ""
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 261acfda..b860a3ea 100644
--- a/tests/modinfo.test
+++ b/tests/modinfo.test
@@ -17,9 +17,9 @@ fi
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 5cc60014..9f44e07c 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 @@ testing "create file" "patch >/dev/null && cat bork" "one\ntwo\nthree\n" "" "
+two
+three
"
+
testing "insert in middle" "patch > /dev/null && cat bork" \
"one\nfour\ntwo\nthree\n" "" "
--- bork
@@ -81,10 +90,29 @@ testing "filter timestamps" "patch > /dev/null && cat bork" \
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 30525c6b..200e2d55 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" "" ""
-
-
-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 "'%3c'" "'%3c' x" " x" "" ""
+testcmd "'%-3c'" "'%-3c' x" "x " "" ""
+testcmd "'%+d'" "'%+d' 5" "+5" "" ""
+
+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" "" ""
-testing "printf \x" "$PRINTF 'A\x1b\x2B\x3Q\xa' | od -An -tx1" \
- " 41 1b 2b 03 51 0a\n" "" ""
+testcmd '\x' "'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 cc728dbf..92e80e8f 100755
--- a/tests/readlink.test
+++ b/tests/readlink.test
@@ -31,13 +31,17 @@ testing "link->link (recursive)" "readlink link" "link\n" "" ""
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 @@ testing "-f /dev/null/file" \
"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 c42fd435..a768ff22 100755
--- a/tests/realpath.test
+++ b/tests/realpath.test
@@ -5,35 +5,62 @@
#testing "name" "command" "result" "infile" "stdin"
TOP="$(readlink -f .)"
+export PWD
-testcmd '' '.' "$TOP\n" '' ''
-#testcmd '-z' '-z . | tr "\0" X' "${TOP}X" '' ''
touch file
-testcmd 'file' 'file' "$TOP/file\n" '' ''
mkdir -p one/two/three
+ln -s ./one uno
+ln -s one/two dos
+
+testcmd '' '.' "$TOP\n" '' ''
+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" '' ''
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 5035478b..ce35161f 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 @@ testing "blank pattern repeats last pattern" \
"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 "range +3" "sed -ne '2,+3p'" "2\n3\n4\n5\n" "" \
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 "bonus backslashes" \
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 @@ testing 'megabyte s/x/y/g (20 sec timeout)' \
'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'
+
+testcmd 's i and I' 's/o/0/ig' "f00l F00L" "" "fool FOOL"
-testing 's i and I' 'sed 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 05d9b1e9..6b80e6ac 100755
--- a/tests/seq.test
+++ b/tests/seq.test
@@ -73,4 +73,6 @@ testing "invalid increment" "seq 1 1f 1 2>/dev/null || echo y" "y\n" "" ""
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 9cfa9fd6..0cc16b9b 100644
--- a/tests/sh.test
+++ b/tests/sh.test
@@ -57,7 +57,7 @@ shxpect() {
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 'arg shift' "$SH -c '"'for i in "" 2 1 1 1; do echo $? $1; shift $i; don
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 @@ testing 'default exports' \
# "{ \$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 @@ testing '${x#short} ${x##long}' 'x=banana; echo ${x#b*n} ${x##b*n}' \
'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 @@ mkdir -p abc/def/ghi
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;;&' 'case wow in w?w) echo ok;;& wow) echo no; esac' 'ok\nno\n' \
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 "IFS3" 'IFS=x; echo "$(echo abx)"' "abx\n" "" ""
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 @@ shxpect 'here2' I$'POTATO=123; cat << E"O"F\n' E"> " \
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 @@ testing '"exit shell" means exit eval but encapsulating function continues' \
'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 @@ shxpect 'blank line preserves $?' \
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 00000000..0e54e76e
--- /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 5fe925e1..dbb6ca08 100755
--- a/tests/sort.test
+++ b/tests/sort.test
@@ -104,6 +104,11 @@ toyonly testing "-kx" "sort -k1,1x" "3\na\n0c\n" "" "0c\na\n3\n"
# "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
index 034a3bfb..e6487bd7 100644..100755
--- 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" "" ""
-
-# 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" \
+ "-rw-rw-r-- root/sys 0 2009-02-13 23:31 file\n" "" ""
+
+# 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" "" ""
-
-# / and .. only stripped from name, not symlink target.
-ln -s ../name.././.. dir/link
-testing "create symlink" "$TAR dir/link | SUM 3" \
- "7324cafbd9aeec5036b6efc54d741f11528aeb10\n" "" ""
+ "d469d4bc06def2d8808400ba30025ca295d05e4f\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" "" ""
+
+# MacOS X has different symlink permissions, skip these tests there
+[ "$(uname)" == Darwin ] && SKIP=999
+
+ # / and .. only stripped from name, not symlink target.
+ ln -s ../name.././.. dir/link
+ testing "create symlink" "$TAR dir/link | SUM 3" \
+ "f841bf9d757c655c5d37f30be62acb7ae24f433c\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 symlnk" "$TAR dir/lshort dir/llong | SUM 3" \
- "8a5d652dc85f252a2e3b3f47d1ecd699e98a5f4b\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" \
- "543116b8e690a116a559ab5b673f9b6d6601c925\n" "" ""
-# absolute and relative link names, broken and not
+ ln -s $LONG dir/${LONG:5}
+ testing "create long->long" "$TAR dir/${LONG:5} | SUM 7" \
+ "b9e24f53e27496c5125445230d201b4a36ff7398\n" "" ""
-ln -s file dir/linkok
-testing "create symlink" "$TAR dir/linkok | SUM 3" \
- "55652846506cf0a9d43b3ef03ccf9e98123befaf\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 @@ testing "-I gzip t" 'LST -Igzip -f "$FILES"/tar/tar.tgz' \
"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 @@ toyonly testing "cat tbz | extract dir/file (autodetect)" \
"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
-
-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" \
- "063fc6519ea2607763bc591cc90dd15ac2b43eb8\n" "" ""
-
-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
-
-testing "sparse double overflow" "$TAR --sparse fweep | SUM 7" \
- "f1fe57f8313a9d682ec9013a80f3798910b6ff51\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 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
-
-testcmd "longname" "tf $FILES/tar/long_path.tar" \
- "$(printf 'long file name%86cTRAILING' ' ' | tr ' ' _)\n" "" ""
+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
+
+# Tests that don't produce the same results on MacOS X as Linux
+[ "$(uname)" == Darwin ] && SKIP=999
+
+ 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
+
+ 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
+
+ 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" \
+ "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" \
+ "807664bcad0e827793318ff742991d6f006b2127\n" "" ""
+ rm fweep2 fweep2.tar
+
+SKIP=0 # End of tests that don't work on MacOS X
mkdir -p links
touch links/orig
@@ -278,14 +304,125 @@ rm -rf one test.tar
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 @@ tar cpf tar.tgz dir/file
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 1295be41..2174f405 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 @@ type_test()
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 @@ for i in uu+s gg+s k+t; do
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 "-ge" "arith_test -ge" "eg" "" ""
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 @@ testing "-le" "arith_test -le" "le" "" ""
# // 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
index 18f93790..694540ae 100644..100755
--- a/tests/timeout.test
+++ b/tests/timeout.test
@@ -23,7 +23,7 @@ testcmd "--preserve-status killed" '--preserve-status -s 9 .1 sleep 100 ; echo $
# 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" '1 ./loop.sh ; echo $?' '124\n' '' ''
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 253af626..2bb08280 100755
--- a/tests/truncate.test
+++ b/tests/truncate.test
@@ -9,7 +9,10 @@ testing "0" "truncate -s 0 freep $SIZE" "0\n" "" ""
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 dc3c7b32..7566e375 100644
--- a/tests/xargs.test
+++ b/tests/xargs.test
@@ -84,3 +84,5 @@ testing "parallel sleep" "
#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 e9ec81ed..3b350a46 100755
--- a/tests/xxd.test
+++ b/tests/xxd.test
@@ -9,45 +9,63 @@ echo -n > file2
# 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 57af1097..878a11d4 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 81c49552..ace3b260 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 struct toy_context {
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 @@ extern char **environ, *toybox_version, toybuf[4096], libbuf[4096];
#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 0f7b387e..005f7146 100644
--- a/toys/android/log.c
+++ b/toys/android/log.c
@@ -23,18 +23,26 @@ config LOG
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 @@ void log_main(void)
}
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 8831cbfb..5eb8fa62 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 54080686..4382e7d6 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 @@ GLOBALS(
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 @@ GLOBALS(
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 @@ void skeleton_main(void)
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 384d6fcd..5ce590c8 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 color(int c)
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 @@ static void format_message(char *msg, int new)
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 @@ void dmesg_main(void)
// 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 049285af..b80e24fe 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 @@ config GZIP
-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 @@ config GUNZIP
-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 @@ static void do_gzip(int ifd, char *in)
{
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 @@ static void do_gzip(int ifd, char *in)
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 @@ void gzip_main(void)
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 daa60cc0..3c15b869 100644
--- a/toys/lsb/hostname.c
+++ b/toys/lsb/hostname.c
@@ -66,7 +66,7 @@ void hostname_main(void)
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 d3546a05..d2a5dd20 100644
--- a/toys/lsb/killall.c
+++ b/toys/lsb/killall.c
@@ -50,6 +50,7 @@ static int kill_process(pid_t pid, char *name)
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 feb403f7..1f83a29d 100644
--- a/toys/lsb/md5sum.c
+++ b/toys/lsb/md5sum.c
@@ -160,8 +160,7 @@ static void md5_transform(void)
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 @@ static void md5_transform(void)
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 @@ static void sha1_transform(void)
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 @@ static void do_hash(int fd, char *name)
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 0986b4fd..530a4a26 100644
--- a/toys/lsb/mktemp.c
+++ b/toys/lsb/mktemp.c
@@ -48,7 +48,7 @@ void mktemp_main(void)
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 @@ void mktemp_main(void)
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 10e8e9e4..109f6e19 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 @@ config MOUNT
#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 @@ GLOBALS(
// 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 @@ GLOBALS(
// 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 @@ static long flag_opts(char *new, long flags, char **more)
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 @@ static void mount_filesystem(char *dev, char *dir, char *type,
}
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 @@ static void mount_filesystem(char *dev, char *dir, char *type,
&& ((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 @@ static void mount_filesystem(char *dev, char *dir, char *type,
// 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 @@ void mount_main(void)
// 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 @@ void mount_main(void)
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 @@ void mount_main(void)
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 @@ void mount_main(void)
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 8c17dc6d..6c822e88 100644
--- a/toys/lsb/passwd.c
+++ b/toys/lsb/passwd.c
@@ -10,7 +10,6 @@ USE_PASSWD(NEWTOY(passwd, ">1a:dlu", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
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 7a931c64..b44d05c6 100644
--- a/toys/lsb/seq.c
+++ b/toys/lsb/seq.c
@@ -52,24 +52,6 @@ static double parsef(char *s)
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 @@ static char *flush_toybuf(char *ss)
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 @@ void seq_main(void)
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 136e81ed..71df8a6b 100644
--- a/toys/lsb/su.c
+++ b/toys/lsb/su.c
@@ -12,7 +12,6 @@ USE_SU(NEWTOY(su, "^lmpu:g:c:s:[!lmp]", TOYFLAG_BIN|TOYFLAG_ROOTONLY))
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 @@ void su_main()
{
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 @@ void su_main()
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 3c9e3ca1..fbaa8e42 100644
--- a/toys/lsb/umount.c
+++ b/toys/lsb/umount.c
@@ -37,7 +37,7 @@ GLOBALS(
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 20331678..f8e54dcc 100644
--- a/toys/net/host.c
+++ b/toys/net/host.c
@@ -38,9 +38,9 @@ static const struct rrt {
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 @@ void host_main(void)
// 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 @@ void host_main(void)
// 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 @@ void host_main(void)
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 @@ void host_main(void)
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 00000000..3cb78421
--- /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 2d80a18f..38348949 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 @@ config NETCAT_LISTEN
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 @@ static void timeout(int signum)
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 @@ static int usock(char *name, int type, int out)
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 @@ void netcat_main(void)
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 @@ void netcat_main(void)
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 @@ void netcat_main(void)
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 @@ void netcat_main(void)
}
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);
-
- if (toys.optc) {
- // Do we need a tty?
+ alarm(0);
-// 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
+ // Fork a child as necessary. Parent cleans up and continues here.
+ if (toys.optc && FLAG(L)) NOEXIT(child = XVFORK());
+ if (child) {
+ close(in1);
+ continue;
+ }
- // Do we need to fork and/or redirect for exec?
+ if (FLAG(u))
+ xconnect(in1, (void *)toybuf, sizeof(struct sockaddr_storage));
-// TODO xpopen_both() here?
+ // 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);
- 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 7eed02da..9470e8e1 100644
--- a/toys/net/netstat.c
+++ b/toys/net/netstat.c
@@ -36,6 +36,42 @@ GLOBALS(
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 1139b0e0..4a216df4 100644
--- a/toys/net/sntp.c
+++ b/toys/net/sntp.c
@@ -20,10 +20,10 @@ config SNTP
-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 6a2cf1ee..12855708 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
index 9e100e87..4e17309a 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
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 @@ config WGET_OPENSSL
#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 @@ GLOBALS(
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 @@ static void wget_info(char *url, char **host, char **port, char **path)
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 @@ static void wget_info(char *url, char **host, char **port, char **path)
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 @@ static void wget_connect(char *host, char *port)
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 @@ static size_t wget_read(void *buf, size_t len)
#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 @@ static void wget_write(void *buf, size_t len)
#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 @@ static void wget_close()
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 void wget_close()
static char *wget_find_header(char *header, char *val)
{
- char *result = strcasestr(header, val);
-
- if (result) {
- result += strlen(val);
- result[strcspn(result, "\r\n")] = 0;
- }
+ if (!(header = strcasestr(header, val))) return 0;
+ header += strlen(val);
- 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 @@ void wget_main(void)
// 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 @@ void wget_main(void)
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 22652fd0..e6c936b6 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 @@ config BASE32
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 01b5971b..bed20b2c 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 @@ config FSTYPE
GLOBALS(
struct arg_list *s;
+ char *o;
)
struct fstype {
@@ -52,6 +54,7 @@ struct fstype {
{"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 @@ struct fstype {
{"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 @@ static void show_tag(char *key, char *value)
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 @@ static void do_blkid(int fd, char *name)
}
// 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 @@ static void do_blkid(int fd, char *name)
} 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 @@ static void do_blkid(int fd, char *name)
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 920d8563..9c4dd871 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 47e1267b..4e893a07 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 @@ config FACTOR
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 @@ static void factor(char *s)
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 a4460ec2..744d67a3 100644
--- a/toys/other/fmt.c
+++ b/toys/other/fmt.c
@@ -27,7 +27,7 @@ config FMT
#include "toys.h"
GLOBALS(
- int width;
+ long width;
int level, pos;
)
diff --git a/toys/other/fsfreeze.c b/toys/other/fsfreeze.c
index b494ce96..ee7bd530 100644
--- a/toys/other/fsfreeze.c
+++ b/toys/other/fsfreeze.c
@@ -7,7 +7,6 @@ USE_FSFREEZE(NEWTOY(fsfreeze, "<1>1f|u|[!fu]", TOYFLAG_USR|TOYFLAG_SBIN))
config FSFREEZE
bool "fsfreeze"
default y
- depends on TOYBOX_FIFREEZE
help
usage: fsfreeze {-f | -u} MOUNTPOINT
@@ -26,6 +25,6 @@ void fsfreeze_main(void)
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 cc3ce64f..14fab5da 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 int comparator(const void *a, const void *b)
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 @@ void gpioinfo_main(void)
#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 1cdbe7e1..18fbed0d 100644
--- a/toys/other/help.c
+++ b/toys/other/help.c
@@ -30,47 +30,51 @@ static void do_help(struct toy_list *t)
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 d3402056..4550dc34 100644
--- a/toys/other/hexedit.c
+++ b/toys/other/hexedit.c
@@ -181,7 +181,7 @@ static void find_prev(int pos)
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 541c70a3..eaec842e 100644
--- a/toys/other/hwclock.c
+++ b/toys/other/hwclock.c
@@ -47,11 +47,11 @@ void hwclock_main()
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 @@ void hwclock_main()
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 bce160df..ad296adf 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 @@ config I2CDETECT
-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 @@ config I2CDUMP
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 @@ config I2CSET
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 @@ printf_format static void confirm(const char *fmt, ...)
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 @@ static unsigned long i2c_get_funcs(int bus)
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 @@ static int i2c_read_byte(int fd, int addr, int *byte)
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 @@ void i2cdetect_main(void)
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 @@ void i2cdetect_main(void)
}
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 @@ void i2cdetect_main(void)
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 (addr<first || addr>last) {
+ printf(" ");
+
+ continue;
+ }
+ if (ioctl(fd, I2C_SLAVE, addr) == -1) {
+ if (errno == EBUSY) {
+ xprintf(" UU");
+ continue;
}
- if ((FLAG(r) ? i2c_read_byte(fd, addr, &byte)
- : i2c_quick_write(fd, addr)) == -1) xprintf(" --");
- else xprintf(" %02x", addr);
+ 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 i2cdetect_main(void)
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 @@ void i2cdump_main(void)
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 i2cdump_main(void)
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 i2cget_main(void)
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 @@ void i2cset_main(void)
} 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 5214b937..62c1293e 100644
--- a/toys/other/login.c
+++ b/toys/other/login.c
@@ -10,7 +10,6 @@ USE_LOGIN(NEWTOY(login, ">1f:ph:", TOYFLAG_BIN|TOYFLAG_NEEDROOT))
config LOGIN
bool "login"
default y
- depends on TOYBOX_SHADOW
help
usage: login [-p] [-h host] [-f USERNAME] [USERNAME]
@@ -38,7 +37,7 @@ static void login_timeout_handler(int sig __attribute__((unused)))
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 @@ void login_main(void)
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 @@ void login_main(void)
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 @@ void login_main(void)
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 ce84c1ef..0973273c 100644
--- a/toys/other/losetup.c
+++ b/toys/other/losetup.c
@@ -71,6 +71,16 @@ static int loopback_setup(char *device, char *file)
}
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 31d7f43a..5be83013 100644
--- a/toys/other/lsattr.c
+++ b/toys/other/lsattr.c
@@ -198,10 +198,11 @@ error:
// 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 @@ static int retell_dir(struct dirtree *root)
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 @@ static int retell_dir(struct dirtree *root)
}
}
free(fpath);
+
return 0;
}
diff --git a/toys/other/lsusb.c b/toys/other/lsusb.c
index 836c4f68..600858bb 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 @@ config LSPCI
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 @@ config LSUSB
GLOBALS(
char *i;
- long n;
+ long x, n;
void *ids, *class;
int count;
@@ -57,7 +58,7 @@ struct scanloop {
// 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 @@ static int scan_uevent(struct dirtree *new, int len, struct scanloop *sl)
// 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 @@ static void get_names(struct dev_ids *ids, int id1, int id2,
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 @@ struct dev_ids *parse_dev_ids(char *name, struct dev_ids **and)
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 @@ static int list_usb(struct dirtree *new)
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 @@ static int list_pci(struct dirtree *new)
}
// 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 @@ static int list_pci(struct dirtree *new)
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 fb83f5e3..813b74b5 100644
--- a/toys/other/mcookie.c
+++ b/toys/other/mcookie.c
@@ -29,7 +29,7 @@ void mcookie_main(void)
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 3106ea8e..806e1821 100644
--- a/toys/other/mkswap.c
+++ b/toys/other/mkswap.c
@@ -42,7 +42,7 @@ void mkswap_main(void)
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 6c1e9392..e1a64ba6 100644
--- a/toys/other/modinfo.c
+++ b/toys/other/modinfo.c
@@ -44,6 +44,7 @@ static void modinfo_file(char *full_name)
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 a97c600a..7985cbb5 100644
--- a/toys/other/mountpoint.c
+++ b/toys/other/mountpoint.c
@@ -23,7 +23,7 @@ config MOUNTPOINT
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 @@ void mountpoint_main(void)
{
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 ad3440af..caa7da61 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 @@ config NBD_CLIENT
#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;
+
+ // Daemonize in a nommu-friendly way, but retain stderr
+ if (toys.stacktop && !FLAG(n)) {
+ dup2(2, 222);
+ xvdaemon();
+ }
+ dup2(222, 2);
+ close(222);
- // Repeat until spanked
+ TT.nbd = xopen(device, O_RDWR);
+ xsignal(SIGINT, sig_cleanup);
+ xsignal(SIGTERM, sig_cleanup);
- nbd = xopen(device, O_RDWR);
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 00000000..98c1937c
--- /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 d0c75d01..104ea1ee 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 @@ config NSENTER
#define setns(fd, nstype) syscall(SYS_setns, fd, nstype)
GLOBALS(
- char *Uupnmi[6];
+ char *UupnmiC[6];
long t;
)
@@ -86,28 +93,9 @@ static void write_ugid_map(char *map, unsigned eugid)
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 @@ static int test_f()
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 @@ void unshare_main(void)
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 @@ void unshare_main(void)
}
// 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++) {
- char *filename = TT.Uupnmi[i];
+ for (i = 0; i<ARRAY_LEN(flags); i++, nsnames += strlen(nsnames)+1) {
+ if (FLAG(a) || (toys.optflags & (1<<i))) {
+ char *filename = TT.UupnmiC[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 4c8bb1f6..c0b0c09d 100644
--- a/toys/other/oneit.c
+++ b/toys/other/oneit.c
@@ -65,13 +65,37 @@ static void oneit_signaled(int signal)
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 @@ void oneit_main(void)
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 8210587d..66d8a360 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 d222f010..91e28272 100644
--- a/toys/other/pmap.c
+++ b/toys/other/pmap.c
@@ -17,7 +17,7 @@ config PMAP
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 @@ void pmap_main(void)
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 @@ void pmap_main(void)
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 @@ void pmap_main(void)
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 c34daf5a..73627561 100644
--- a/toys/other/pwgen.c
+++ b/toys/other/pwgen.c
@@ -51,7 +51,7 @@ void pwgen_main(void)
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 29e27244..1db6b69a 100644
--- a/toys/other/readelf.c
+++ b/toys/other/readelf.c
@@ -124,6 +124,8 @@ static int find_section(char *spec, struct sh *s)
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 @@ static void scan_elf()
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 @@ static void scan_elf()
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 @@ static void scan_elf()
}
}
- 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 @@ static void scan_elf()
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 3155dcc5..2acdd558 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 @@ config READLINK
-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;
+ if (!presolve(&TT.relative_base)) presolve(&TT.R);
+
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 (s) {
- if (!FLAG(q)) xprintf("%s%s", s, (FLAG(n) && !arg[1]) ? "" : "\n");
- free(s);
- } else toys.exitval = 1;
+ 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 ee951e03..b35c57f0 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 @@ static void do_sha3sum(int fd, char *name)
}
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 1932f758..9c13f6bd 100644
--- a/toys/other/shred.c
+++ b/toys/other/shred.c
@@ -90,7 +90,7 @@ void shred_main(void)
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 00000000..fe8230f1
--- /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 98f27ed6..463aa46a 100644
--- a/toys/other/stat.c
+++ b/toys/other/stat.c
@@ -157,13 +157,13 @@ static void print_statfs(char type) {
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 @@ void stat_main(void)
// 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 @@ void stat_main(void)
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 fb171300..bd6a41a9 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 2a9ae029..a3d0ffb3 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 @@ config TASKSET
#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 @@ static void do_taskset(pid_t pid, int quiet)
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 void do_taskset(pid_t pid, int quiet)
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 taskset_main(void)
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 proc
- if (!nproc) nproc = sysconf(_SC_NPROCESSORS_CONF);
+ // 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);
+ }
- xprintf("%u\n", nproc);
+ xprintf("%u\n", nproc ? : 1);
}
diff --git a/toys/other/timeout.c b/toys/other/timeout.c
index e93a806c..ed4956a4 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 @@ config TIMEOUT
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 @@ config TIMEOUT
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);
-
- 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");
- }
+ siglongjmp(TT.sj, 1);
+}
+
+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;
-
- 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");
-
- status = xwaitpid(TT.pid);
- if (FLAG(preserve_status) || !toys.exitval) toys.exitval = status;
+ TT.pfd.events = POLLIN;
+ TT.fds[1] = -1;
+ if (sigsetjmp(TT.sj, 1)) goto done;
+ xsignal_flags(SIGCHLD, handler, SA_NOCLDSTOP);
+
+ 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);
+
+ 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 6c0c8052..237bba63 100644
--- a/toys/other/uptime.c
+++ b/toys/other/uptime.c
@@ -9,7 +9,6 @@ USE_UPTIME(NEWTOY(uptime, ">0ps", TOYFLAG_USR|TOYFLAG_BIN))
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 6040cc06..e09a17c8 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 d5cf5691..94502f1f 100644
--- a/toys/other/vmstat.c
+++ b/toys/other/vmstat.c
@@ -29,125 +29,124 @@ config VMSTAT
#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);
+
+ xreadfile("/proc/uptime", toybuf, sizeof(toybuf));
+ sscanf(toybuf, "%*s %llu", &units);
- 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);
+ 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 a76c82f5..c271e8bd 100644
--- a/toys/other/w.c
+++ b/toys/other/w.c
@@ -7,7 +7,6 @@ USE_W(NEWTOY(w, NULL, TOYFLAG_USR|TOYFLAG_BIN))
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 0402d3ee..c3268a14 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 3a070dff..a37b0e3e 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 @@ static void do_xxd(int fd, char *name)
{
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 @@ static void do_xxd(int fd, char *name)
}
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, 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++;
+ }
+ }
- for (i=0; i<len;) {
- space -= printf("%02x", toybuf[i]);
- if (!(++i%TT.g)) {
+ 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 int dehex(char ch)
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 @@ static void do_xxd_reverse(int fd, char *name)
// 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 @@ static void do_xxd_reverse(int fd, char *name)
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 @@ static void do_xxd_reverse(int fd, char *name)
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 37131404..1288fabb 100644
--- a/toys/pending/bc.c
+++ b/toys/pending/bc.c
@@ -5370,7 +5370,7 @@ size_t bc_program_insertFunc(BcProgram *p, char *name) {
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 78084289..49be5c48 100644
--- a/toys/pending/bootchartd.c
+++ b/toys/pending/bootchartd.c
@@ -14,11 +14,11 @@ config BOOTCHARTD
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 @@ static int dump_proc_data(FILE *fp)
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 @@ static int parse_config_file(char *fname)
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 @@ static char *create_tmp_dir()
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 @@ static void stop_logging(char *tmp_dir, char *prog)
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 60178518..c007618f 100644
--- a/toys/pending/brctl.c
+++ b/toys/pending/brctl.c
@@ -143,12 +143,12 @@ void br_addif(char **argv)
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 @@ void br_delif(char **argv)
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 199e5914..9a4d6df2 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 @@ config DD
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]
-
- Copy/convert files.
-
- 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
-
- FLAGS is a comma-separated list of:
-
- 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
-
- 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).
+ usage: dd [if|of=FILE] [ibs|obs|bs|count|seek|skip=N] [conv|status|iflag|oflag=FLAG[,FLAG...]]
+
+ Copy/convert blocks of data from input to output, with the following
+ keyword=value modifiers (and their default values):
+
+ 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)
+
+ Each =N value accepts the normal unit suffixes (see toybox --help).
+
+ These modifiers take a comma separated list of potential options:
+
+ 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 @@ config DD
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 @@ struct dd_flag {
};
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 const struct dd_flag dd_oflag[] = TAGGED_ARRAY(DD_oflag,
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 @@ static void status()
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 @@ static void parse_flags(char *what, char *arg,
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 @@ void dd_main()
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 @@ void dd_main()
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 @@ void dd_main()
}
// 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 @@ void dd_main()
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 @@ void dd_main()
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 4dd01653..f12b4a3c 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 @@ struct diff {
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 @@ enum {
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 @@ static struct candidate * new_candidate (int i, int j, struct candidate* prev)
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 @@ static void free_candidates(struct candidate *c)
* 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 @@ static int read_tok(FILE *fp, off_t *off, int tok)
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 @@ static int read_tok(FILE *fp, off_t *off, int tok)
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 @@ int bcomp(const void *a, const void *b)
* 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 @@ static int * create_j_vector()
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((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;
+ 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;
}
- 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 @@ static int *diff(char **files)
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 (!file[i].fp){
- perror_msg("%s",files[i]);
- TT.status = 2;
- return NULL; //return SAME
+ 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);
+
+ 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 @@ static void add_to_list(struct dirtree *node)
{
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 @@ static int list_dir (struct dirtree *node)
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 list_dir (struct dirtree *node)
}
}
-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;
-
- // 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++;
+ char *to = "abfnrtv\"\\", *from = "\a\b\f\n\r\t\v\"\\", *s, *t=0, *u;
+ int len, quote = 0;
+
+ 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 show_label(char *prefix, char *filename, struct stat *sb)
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 @@ static void do_diff(char **files)
}
}
- 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.
-
- 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);
+ TT.differ = change; //update status, may change bcoz of -w etc.
+
+ 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(' ');
-
- 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');
+ 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 (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 @@ calc_ct:
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 @@ static void create_empty_entry(int l , int r, int j)
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 @@ static void diff_dir(int *start)
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.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 ((TT.st[0].st_ino == TT.st[1].st_ino) //physicaly same device
- && (TT.st[0].st_dev == TT.st[1].st_dev)) {
+ 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 @@ void diff_main(void)
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 dcef314b..225db579 100644
--- a/toys/pending/getopt.c
+++ b/toys/pending/getopt.c
@@ -22,6 +22,7 @@ config GETOPT
#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 00000000..82421483
--- /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 05afb718..9f4e7ba6 100644
--- a/toys/pending/init.c
+++ b/toys/pending/init.c
@@ -124,6 +124,7 @@ static void parse_inittab(void)
{
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 @@ static void parse_inittab(void)
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 e4b53112..2748854a 100644
--- a/toys/pending/lsof.c
+++ b/toys/pending/lsof.c
@@ -42,8 +42,7 @@ struct file_info {
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 @@ static void print_info(void *data)
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 @@ static void fill_flags(struct file_info *fi)
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 @@ static struct file_info *add_socket(ino_t inode, const char *type)
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 @@ static int find_socket(struct file_info *fi, long inode)
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 @@ static void fill_stat(struct file_info *fi, const char *path)
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 ee0a5b11..0741157f 100644
--- a/toys/pending/mke2fs.c
+++ b/toys/pending/mke2fs.c
@@ -342,9 +342,7 @@ static void check_treelinks(struct dirtree *tree)
// 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 45f8ea21..133d8785 100644
--- a/toys/pending/modprobe.c
+++ b/toys/pending/modprobe.c
@@ -444,7 +444,7 @@ static void go_probe(struct module_s *m)
}
// 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 @@ void modprobe_main(void)
}
// 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 8f45c172..2bdf64a3 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 @@ config SH
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 @@ GLOBALS(
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 @@ GLOBALS(
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 @@ GLOBALS(
// 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 const char *redirectors[] = {"<<<", "<<-", "<<", "<&", "<>", "<", ">>",
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 @@ void debug_show_fds()
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,11 +509,42 @@ static struct sh_vars *findvar(char *name, struct sh_fcall **pff)
return 0;
}
+// get value of variable starting at s.
+static char *getvar(char *s)
+{
+ struct sh_vars *var = findvar(s, 0);
+
+ if (!var) return 0;
+
+ if (var->flags & VAR_MAGIC) {
+ char c = *var->str;
+
+ if (c == 'S') sprintf(toybuf, "%lld", (millitime()-TT.SECONDS)/1000);
+ else if (c == 'R') sprintf(toybuf, "%ld", random()&((1<<16)-1));
+ else if (c == 'L') sprintf(toybuf, "%u", TT.ff->pl->lineno);
+ else if (c == 'G') sprintf(toybuf, "TODO: GROUPS");
+ else if (c == 'B') sprintf(toybuf, "%d", getpid());
+ else if (c == 'E') {
+ struct timespec ts;
+
+ clock_gettime(CLOCK_REALTIME, &ts);
+ sprintf(toybuf, "%lld%c%06ld", (long long)ts.tv_sec, (s[5]=='R')*'.',
+ ts.tv_nsec/1000);
+ }
+
+ return toybuf;
+ }
+
+ 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&31))
- ff->vars = xrealloc(ff->vars, (ff->varslen+32)*sizeof(*ff->vars));
+ 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;
@@ -452,107 +552,222 @@ static struct sh_vars *addvar(char *s, struct sh_fcall *ff)
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
+// 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 cc = **nospace(ss);
+ char *var = 0, *val, cc = **nospace(ss);
+ int ii, noa = lvl&NO_ASSIGN;
+ lvl &= NO_ASSIGN-1;
- // TODO: assignable (variable)
- // Always start handling unary prefixes, parenthetical blocks, and constants
- if (cc=='+' || cc=='-') {
+ // Unary prefixes can only occur at the start of a parse context
+ if (cc=='!' || cc=='~') {
++*ss;
- if (!recalculate(dd, ss, 1)) return 0;
- if (cc=='-') *dd = -*dd;
+ 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, 1)) return 0;
+ if (!recalculate(dd, ss, noa|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==')')) {
+ } 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;
- } else return 0;
+ }
+
+ // 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));
- // x^y binds first
- if (lvl<4) while (strstart(nospace(ss), "**")) {
- if (!recalculate(&ee, ss, 4)) return 0;
+ 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<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;
+ 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<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;
+ 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;
}
- nospace(ss);
- return 1;
-}
+ // x<<y >>
-static int calculate(long long *ll, char *equation)
-{
- char *ss = equation;
+ 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;
+ }
- // 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));
+ // 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);
+ }
- return 0;
+ 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
-int getutf8(char *s, int len, int *cc)
+static int getutf8(char *s, int len, int *cc)
{
unsigned wc;
@@ -563,33 +778,45 @@ int getutf8(char *s, int len, int *cc)
return len;
}
-// get value of variable starting at s.
-static char *getvar(char *s)
+// 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)
{
- struct sh_vars *var = findvar(s, 0);
+ unsigned wc1, wc2;
+ int ll;
- if (!var) return 0;
+ 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;
+ }
+ }
+ }
- if (var->flags & VAR_MAGIC) {
- char c = *var->str;
+ return 0;
+}
- if (c == 'S') sprintf(toybuf, "%lld", (millitime()-TT.SECONDS)/1000);
- else if (c == 'R') sprintf(toybuf, "%ld", random()&((1<<16)-1));
- else if (c == 'L') sprintf(toybuf, "%u", TT.ff->pl->lineno);
- else if (c == 'G') sprintf(toybuf, "TODO: GROUPS");
- else if (c == 'B') sprintf(toybuf, "%d", getpid());
- else if (c == 'E') {
- struct timespec ts;
+// return length of match found at this point (try is null terminated array)
+static int anystart(char *s, char **try)
+{
+ char *ss = s;
- clock_gettime(CLOCK_REALTIME, &ts);
- sprintf(toybuf, "%lld%c%06ld", (long long)ts.tv_sec, (s[5]=='R')*'.',
- ts.tv_nsec/1000);
- }
+ while (*try) if (strstart(&s, *try++)) return s-ss;
- return toybuf;
- }
+ return 0;
+}
- return varend(var->str)+1;
+// 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
@@ -655,7 +882,13 @@ static struct sh_vars *setvar_found(char *s, int freeable, struct sh_vars *var)
// 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 @@ static struct sh_vars *setvar_long(char *s, int freeable, struct sh_fcall *ff)
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 @@ static int unsetvar(char *name)
{
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 @@ static int unsetvar(char *name)
// 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 @@ static char *declarep(struct sh_vars *var)
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 @@ static int redir_prefix(char *word)
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 @@ static char *parse_word(char *start, int early, int quote)
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 @@ static int save_redirect(int **rd, int from, int to)
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 @@ static char *pl2str(struct sh_pipeline *pl, int one)
// 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 @@ static void call_function(void)
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 @@ static int pipe_subshell(char *s, int len, int out)
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 @@ char *wildcard_path(char *pattern, int off, struct sh_arg *deck, int *idx,
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 @@ char *slashcopy(char *s, char *c, struct sh_arg *deck)
#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 @@ static int expand_arg_nobrace(struct sh_arg *arg, char *str, unsigned flags,
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 @@ static int expand_arg_nobrace(struct sh_arg *arg, char *str, unsigned flags,
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 @@ static int expand_arg_nobrace(struct sh_arg *arg, char *str, unsigned flags,
// 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 @@ static int expand_arg_nobrace(struct sh_arg *arg, char *str, unsigned flags,
// 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 @@ static int expand_arg_nobrace(struct sh_arg *arg, char *str, unsigned flags,
} 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 @@ barf:
}
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 @@ barf:
}
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 @@ barf:
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 @@ fail:
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 @@ static int expand_arg(struct sh_arg *arg, char *old, unsigned flags,
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] == '}')) {
+
+ // 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;
- // 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) {
+ 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]=='.') {
- bnext->commas[2] = old[j];
- bnext->commas[3] = old[j+3];
+ bb->commas[2] = old[j];
+ bb->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;
+ (sscanf(old+j+4, "..%u}%n", bb->commas+4, &k) && k))
+ bb->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;
+ 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 (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;
+ 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 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] == '{') {
- dlist_add_nomalloc((void *)&blist,
- (void *)(bb = xzalloc(sizeof(struct sh_brace)+34*4)));
- bb->commas[0] = i;
- // no active span?
- } else if (!bb) continue;
+ // 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 @@ static int expand_arg(struct sh_arg *arg, char *old, unsigned flags,
// 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 @@ static int expand_arg(struct sh_arg *arg, char *old, unsigned flags,
}
// 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 @@ static char *expand_one_arg(char *new, unsigned flags, struct arg_list **del)
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 @@ static struct sh_process *expand_redir(struct sh_arg *arg, int skip, int *urd)
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 @@ static struct sh_process *expand_redir(struct sh_arg *arg, int skip, int *urd)
}
// 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 @@ static struct sh_process *expand_redir(struct sh_arg *arg, int skip, int *urd)
// 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 @@ static struct sh_process *expand_redir(struct sh_arg *arg, int skip, int *urd)
}
// 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 @@ static struct sh_process *expand_redir(struct sh_arg *arg, int skip, int *urd)
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 @@ static struct sh_process *run_command(void)
{
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 @@ static struct sh_process *run_command(void)
// 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 @@ static struct sh_process *run_command(void)
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 @@ static struct sh_process *run_command(void)
}
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 @@ static int parse_line(char *line, struct sh_pipeline **ppl,
// 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 @@ static int parse_line(char *line, struct sh_pipeline **ppl,
// 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);
+ for (pl3 = *ppl;;) {
+ if (pl3->end == pl2) pl3->end = pl;
+ if ((pl3 = pl3->next) == *ppl) break;
+ }
// 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].v = xzalloc(2*sizeof(void *))) = arg->v[++i];
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;
- }
-
- // 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;
}
+ // 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 @@ static int parse_line(char *line, struct sh_pipeline **ppl,
// 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 @@ funky:
// 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 @@ funky:
}
// 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 @@ funky:
// 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 @@ funky:
}
// "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 @@ funky:
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 @@ funky:
} 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 @@ funky:
continue;
// flow control is the first word of a pipeline segment
- } else if (arg->c>1) continue;
-
- // 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';
+ } else if (arg->c>1) {
+ // Except that [[ ]] is a type 0 segment
+ if (ex && *ex==']' && !strcmp(s, ex)) free(dlist_lpop(expect));
- 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 @@ funky:
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 @@ funky:
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 @@ funky:
// 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 @@ static char *get_next_line(FILE *ff, int prompt)
// 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 @@ static void run_lines(void)
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 @@ static void run_lines(void)
// 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 @@ static void run_lines(void)
// 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 @@ dprintf(2, "TODO skipped init for((;;)), need math parser\n");
}
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 @@ dprintf(2, "TODO skipped init for((;;)), need math parser\n");
}
} 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 @@ int do_source(char *name, FILE *ff)
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 @@ int do_source(char *name, FILE *ff)
// 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 @@ is_binary:
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 @@ static void nommu_reentry(void)
// 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 @@ static void subshell_setup(void)
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 @@ void source_main(void)
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 ae8fca9f..e340a4f7 100644
--- a/toys/pending/strace.c
+++ b/toys/pending/strace.c
@@ -33,9 +33,6 @@ GLOBALS(
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,5,11,6};
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 char *strerrno(int e)
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 @@ static void print_struct(long addr)
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 @@ static void print_flags(long v)
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 @@ static void print_flags(long v)
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 @@ static void print_args()
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 @@ static void print_enter(void)
}
} 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 @@ static void print_enter(void)
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 @@ static void print_enter(void)
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 c773e639..f58754bc 100644
--- a/toys/pending/sulogin.c
+++ b/toys/pending/sulogin.c
@@ -13,7 +13,6 @@ USE_SULOGIN(NEWTOY(sulogin, "t#<0=0", TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
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 e5bd76b5..fb0aa77d 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 @@ config TCPSVD
#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 @@ static void insert(struct list_pid **l, int pid, char *addr)
}
// 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 @@ static void handle_exit(int sig)
{
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 @@ static int create_bind_sock(char *host, struct sockaddr *haddr)
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 @@ static int create_bind_sock(char *host, struct sockaddr *haddr)
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 int create_bind_sock(char *host, struct sockaddr *haddr)
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 @@ void tcpsvd_main(void)
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 @@ void tcpsvd_main(void)
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 @@ void tcpsvd_main(void)
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 @@ void tcpsvd_main(void)
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 bbb0a90b..9e743dc3 100644
--- a/toys/pending/vi.c
+++ b/toys/pending/vi.c
@@ -12,9 +12,11 @@ config VI
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 @@ config VI
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 @@ GLOBALS(
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 @@ static char* utf8_last(char* str, int size)
{
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 @@ static int insert_str(const char *data, size_t offset, size_t size, size_t len,
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 @@ static int insert_str(const char *data, size_t offset, size_t size, size_t len,
(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 @@ static int cut_str(size_t offset, size_t len)
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 @@ static int cut_str(size_t offset, size_t len)
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 @@ static size_t text_filesize()
{
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 @@ static char text_byte(size_t offset)
{
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 int text_codepoint(char *dest, size_t offset)
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 @@ static size_t text_strstr(size_t offset, char *str)
{
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 @@ static void block_list_free(void *node)
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 @@ static void linelist_unload()
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;
+ 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 0;
- }
- insert_str(xmmap(0, size, PROT_READ, MAP_SHARED, fd, 0), 0, size,size,MMAP);
- xclose(fd);
- TT.filesize = text_filesize();
+ 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;
}
- return 1;
+ 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 @@ static void check_cursor_bounds()
{
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 @@ static void check_cursor_bounds()
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 @@ static void adjust_screen_buffer()
TT.scr_row = s;
TT.cur_row = c;
-
}
//TODO search yank buffer by register
@@ -672,8 +716,7 @@ static int vi_delete(char reg, size_t from, int flags)
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 vi_change(char reg, size_t to, int flags)
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_right(int count0, int count1, char *unused)
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_up(int count0, int count1, char *unused)
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 @@ static int vi_x(char reg, int count0, int count1)
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 @@ static int vi_push(char reg, int count0, int count1)
//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 @@ static int vi_find_next(char reg, int count0, int count1)
// 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 @@ struct vi_special_param vi_special[] =
{"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 @@ struct vi_mov_param vi_movs[] =
//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 @@ static int run_vi_cmd(char *cmd)
{
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 @@ static int run_vi_cmd(char *cmd)
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 @@ static int run_vi_cmd(char *cmd)
}
+// 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 int crunch_nstr(char **str, int width, int n, FILE *out, char *escmore,
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 @@ static void draw_page()
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 @@ void vi_main(void)
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 @@ void vi_main(void)
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 @@ void vi_main(void)
// 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 @@ void vi_main(void)
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 @@ void vi_main(void)
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 @@ void vi_main(void)
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 @@ void vi_main(void)
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 @@ void vi_main(void)
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 6daba7a2..1eb15d49 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 @@ config CATV
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 @@ static void do_cat(int fd, char *name)
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 @@ void cat_main(void)
{
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 a63272a5..73c4b223 100644
--- a/toys/posix/chgrp.c
+++ b/toys/posix/chgrp.c
@@ -44,24 +44,24 @@ GLOBALS(
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 @@ void chgrp_main(void)
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 6e5b915c..8bb6f815 100644
--- a/toys/posix/cksum.c
+++ b/toys/posix/cksum.c
@@ -39,24 +39,23 @@ GLOBALS(
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 @@ static void do_cksum(int fd, char *name)
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 8e33c92d..2621e25b 100644
--- a/toys/posix/cmp.c
+++ b/toys/posix/cmp.c
@@ -34,11 +34,10 @@ GLOBALS(
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 @@ static void do_cmp(int fd, char *name)
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 @@ static void do_cmp(int fd, char *name)
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 @@ out:
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 2d118b7b..91359246 100644
--- a/toys/posix/comm.c
+++ b/toys/posix/comm.c
@@ -43,26 +43,26 @@ void comm_main(void)
{
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 @@ void comm_main(void)
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 7b9889a2..c11da163 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 @@ static int cp_node(struct dirtree *try)
// 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 @@ static int cp_node(struct dirtree *try)
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 @@ void cp_main(void)
// "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 @@ void cp_main(void)
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 @@ void cp_main(void)
// 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 @@ void mv_main(void)
// 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 @@ void install_main(void)
}
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 5ecd56df..bbcde4b5 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 @@ static unsigned x8u(char *hex)
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 @@ void cpio_main(void)
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 @@ void cpio_main(void)
// 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 @@ void cpio_main(void)
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 @@ void cpio_main(void)
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 @@ void cpio_main(void)
// 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 @@ void cpio_main(void)
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)));
-
- // Set ownership and 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;
-
- if (fd != -1 && !fstat(fd, &st) && (st.st_mode&S_IFMT) == (mode&S_IFMT))
- err = fchown(fd, uid, gid);
- else err = 1;
+ } 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)));
- close(fd);
+ // 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 (!err) {
- struct timespec times[2];
+ // Set timestamp.
+ if (!test && !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 @@ void cpio_main(void)
// 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 c4f34f95..b9710ea5 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 @@ config CUT
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 99a41695..5a0f27e1 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 @@ void date_main(void)
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 caf8cf89..e07b33bf 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 @@ static void show_mt(struct mtab_list *mt, int measuring)
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 86118676..8bf9575d 100644
--- a/toys/posix/du.c
+++ b/toys/posix/du.c
@@ -89,17 +89,15 @@ static int seen_inode(void **list, struct stat *st)
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 @@ static int do_du(struct dirtree *node)
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 @@ static int do_du(struct dirtree *node)
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 2e65bcfa..e48a5472 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 @@ static void do_elf_file(int fd)
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 @@ static void do_regular_file(int fd, char *name)
{
char *s = toybuf;
unsigned len, magic;
+ int ii;
// zero through elf shnum, just in case
memset(s, 0, 80);
@@ -215,6 +216,8 @@ static void do_regular_file(int fd, char *name)
// 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 @@ static void do_regular_file(int fd, char *name)
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 @@ static void do_regular_file(int fd, char *name)
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 @@ static void do_regular_file(int fd, char *name)
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 @@ static void do_regular_file(int fd, char *name)
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 @@ static void do_regular_file(int fd, char *name)
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 @@ static void do_regular_file(int fd, char *name)
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 @@ static void do_regular_file(int fd, char *name)
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 @@ static void do_regular_file(int fd, char *name)
(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 @@ static void do_regular_file(int fd, char *name)
(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 bca7c67b..f82817ca 100644
--- a/toys/posix/find.c
+++ b/toys/posix/find.c
@@ -29,19 +29,19 @@ config FIND
-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 @@ config FIND
-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 @@ static int do_find(struct dirtree *new)
// 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 @@ static int do_find(struct dirtree *new)
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 @@ static int do_find(struct dirtree *new)
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 @@ static int do_find(struct dirtree *new)
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 @@ static int do_find(struct dirtree *new)
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 @@ static int do_find(struct dirtree *new)
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 @@ static int do_find(struct dirtree *new)
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 0474f7db..137c9c3c 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 @@ GLOBALS(
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 @@ static void outline(char *line, char dash, char *name, long lcount, long bcount,
{
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 @@ static void do_grep(int fd, char *name)
// 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;
+
+ mm->rm_so = mm->rm_eo = 0;
+ rc = 1;
+
+ // 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;
- // Handle "fixed" (literal) matches
- if (FLAG(F)) {
- struct arg_list *seek, fseek;
- char *s = 0;
-
- 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);
-
- if (s) break;
+ goto got;
}
+ if (FLAG(x)) break;
+ }
- if (s) {
- 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);
- }
+ // 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 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 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;
}
}
if (!rc && FLAG(o) && !mm->rm_eo && ulen>start-line) {
- start++;
+ move = 1;
continue;
}
@@ -238,7 +235,7 @@ static void do_grep(int fd, char *name)
if (!isalnum(c) && c != '_') c = 0;
}
if (c) {
- start += mm->rm_so+1;
+ move = mm->rm_so+1;
continue;
}
}
@@ -247,7 +244,7 @@ static void do_grep(int fd, char *name)
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 @@ static void do_grep(int fd, char *name)
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 @@ static void do_grep(int fd, char *name)
}
}
- 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 @@ static void do_grep(int fd, char *name)
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 @@ static void do_grep(int fd, char *name)
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 void do_grep(int fd, char *name)
}
}
+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 @@ static void parse_regex(void)
}
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);
+
+ // 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++;
}
- dlist_terminate(TT.reg);
+ 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 @@ static int do_grep_r(struct dirtree *new)
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 @@ void grep_main(void)
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 d5c0700c..04e1658c 100644
--- a/toys/posix/head.c
+++ b/toys/posix/head.c
@@ -34,7 +34,7 @@ GLOBALS(
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 @@ static void do_head(int fd, char *name)
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 d2721672..0674f3db 100644
--- a/toys/posix/iconv.c
+++ b/toys/posix/iconv.c
@@ -11,7 +11,6 @@ USE_ICONV(NEWTOY(iconv, "cst:f:", TOYFLAG_USR|TOYFLAG_BIN))
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 2eaba031..2f47f60f 100644
--- a/toys/posix/kill.c
+++ b/toys/posix/kill.c
@@ -144,8 +144,9 @@ void kill_main(void)
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 3cd5c7b8..65e1d46a 100644
--- a/toys/posix/ln.c
+++ b/toys/posix/ln.c
@@ -52,13 +52,15 @@ void ln_main(void)
} 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 906d64f4..427a5f5c 100644
--- a/toys/posix/logger.c
+++ b/toys/posix/logger.c
@@ -26,6 +26,8 @@ config LOGGER
GLOBALS(
char *p, *t;
+
+ int priority;
)
// find str in names[], accepting unambiguous short matches
@@ -48,9 +50,15 @@ static int arrayfind(char *str, char *names[], int len)
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 @@ void logger_main(void)
"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 @@ void logger_main(void)
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 @@ void logger_main(void)
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 15511059..56d5c638 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 @@ config LS
// 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 @@ static void entrylen(struct dirtree *dt, unsigned *len)
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;
-
- 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;
- }
- 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;
+ char *ss = TT.sort;
+ long long ll = 0;
+ int ret = 0;
+
+// 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 (!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 @@ static int filter(struct dirtree *new)
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 @@ static void listfiles(int dirfd, struct dirtree *indir)
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 @@ static void listfiles(int dirfd, struct dirtree *indir)
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 @@ static void listfiles(int dirfd, struct dirtree *indir)
// 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 @@ static void listfiles(int dirfd, struct dirtree *indir)
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 @@ void ls_main(void)
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 @@ void ls_main(void)
// 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 90d374ef..48eb38c6 100644
--- a/toys/posix/nohup.c
+++ b/toys/posix/nohup.c
@@ -21,17 +21,14 @@ config NOHUP
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 @@ void nohup_main(void)
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 f0edcd76..c12055e6 100644
--- a/toys/posix/od.c
+++ b/toys/posix/od.c
@@ -56,8 +56,8 @@ static int od_out_t(struct odtype *t, char *buf, int *offset)
// 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 @@ static int od_out_t(struct odtype *t, char *buf, int *offset)
// 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 int od_out_t(struct odtype *t, char *buf, int *offset)
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 @@ static void od_outline(void)
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 @@ static void do_od(int fd, char *name)
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 @@ void od_main(void)
// 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 4b8c61c3..6bdd4615 100644
--- a/toys/posix/patch.c
+++ b/toys/posix/patch.c
@@ -143,7 +143,7 @@ static int loosecmp(char *aa, char *bb)
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 @@ static int apply_one_hunk(void)
// 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 @@ static int apply_one_hunk(void)
}
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 @@ static int apply_one_hunk(void)
// 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 @@ fuzzed:
}
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 @@ done:
// 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 @@ static char *unquote_file(char *filename)
}
*t = 0;
- return filename;
+ return newfile;
}
// Read a patch file and find hunks, opening/creating/deleting files.
@@ -313,7 +313,7 @@ static char *unquote_file(char *filename)
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 @@ void patch_main(void)
// 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 @@ void patch_main(void)
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 @@ void patch_main(void)
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 @@ void patch_main(void)
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 2cbf3035..93374731 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 @@ config PRINTF
#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 @@ static int handle_slash(char **esc_val, int posix)
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 @@ void printf_main(void)
// 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 @@ void printf_main(void)
*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 @@ void printf_main(void)
// 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 @@ void printf_main(void)
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 3884097b..2ff3ba73 100644
--- a/toys/posix/ps.c
+++ b/toys/posix/ps.c
@@ -209,7 +209,10 @@ GLOBALS(
} 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 @@ static void help_help(void)
// 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 @@ static int shared_match_process(long long *slot)
// 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 @@ static int get_ps(struct dirtree *new)
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 @@ static long long get_headers(struct ofields *field, char *buf, int blen)
// 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 @@ void ps_main(void)
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 @@ static void top_common(
"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 @@ static void top_common(
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 @@ static int iotop_filter(long long *oslot, long long *nslot, int milis)
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 @@ static void do_pgk(struct procpid *tb)
}
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 @@ static void match_pgrep(void *p)
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 c7dc78f7..c6f45ad0 100644
--- a/toys/posix/pwd.c
+++ b/toys/posix/pwd.c
@@ -41,8 +41,7 @@ void pwd_main(void)
// 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 be611e67..cfe282f7 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 cea12ea5..0de90633 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 @@ config SED
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 @@ GLOBALS(
// 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 @@ struct sedcmd {
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];
-
- if (TT.noeol && !writeall(TT.fdout, "\n", 1)) return 1;
+ int l = len, old = line[len];
+
+ 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 @@ static char *extend_string(char **old, char *new, int oldlen, int newlen)
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 @@ static void sed_line(char **pline, long plen)
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;
-
- // 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;
+ if (FLAG(tarxform)) {
+ if (!pline) return;
+
+ 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 @@ static void sed_line(char **pline, long plen)
} 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 @@ static void sed_line(char **pline, long plen)
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 @@ static void sed_line(char **pline, long plen)
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 @@ static void sed_line(char **pline, long plen)
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 @@ static void sed_line(char **pline, long plen)
// 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 @@ static void sed_line(char **pline, long plen)
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 @@ static void sed_line(char **pline, long plen)
// 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 @@ static void sed_line(char **pline, long plen)
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 @@ static void sed_line(char **pline, long plen)
}
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 @@ static void sed_line(char **pline, long plen)
char *name;
writenow:
+ if (FLAG(tarxform)) error_exit("tilt");
+
// Swap out emit() context
fd = TT.fdout;
noeol = TT.noeol;
@@ -572,9 +631,10 @@ writenow:
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 @@ done:
// 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 @@ done:
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 @@ static void parse_pattern(char **pline, long len)
}
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 @@ static void parse_pattern(char **pline, long len)
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 @@ resume_s:
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:
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 @@ void sed_main(void)
(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 @@ void sed_main(void)
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 73f03fb4..0eb22702 100644
--- a/toys/posix/sleep.c
+++ b/toys/posix/sleep.c
@@ -11,7 +11,7 @@ config SLEEP
bool "sleep"
default y
help
- usage: sleep DURATION
+ usage: sleep DURATION...
Wait before exiting.
@@ -24,7 +24,10 @@ config SLEEP
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 c06b2a5f..c0d312de 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 @@ config SORT
-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 @@ static void sort_lines(char **pline, long len)
*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_lines(char **pline, long len)
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 @@ void sort_main(void)
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 @@ void sort_main(void)
// 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 f34e10cc..514bd5b8 100644
--- a/toys/posix/tail.c
+++ b/toys/posix/tail.c
@@ -36,8 +36,7 @@ GLOBALS(
struct {
char *path;
int fd;
- dev_t dev;
- ino_t ino;
+ struct dev_ino di;
} *F;
)
@@ -159,12 +158,12 @@ static void tail_continue()
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 @@ static void do_tail(int fd, char *name)
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 @@ void tail_main(void)
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 @@ void tail_main(void)
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 9cf1a5c9..ea8edbf7 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 @@ config TAR
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 @@ config TAR
--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 @@ GLOBALS(
} 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 @@ static void maybe_prefix_block(char *data, int check, int type)
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 @@ static void alloread(void *buf, int len)
(*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 @@ static int add_to_tar(struct dirtree *node)
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 @@ static int add_to_tar(struct dirtree *node)
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 @@ static int add_to_tar(struct dirtree *node)
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 @@ static int add_to_tar(struct dirtree *node)
// 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 @@ static int add_to_tar(struct dirtree *node)
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 @@ error:
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 @@ static void extract_to_disk(void)
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 @@ static void unpack_tar(char *first)
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 @@ static void unpack_tar(char *first)
}
}
- // 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 @@ static void unpack_tar(char *first)
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 @@ static void unpack_tar(char *first)
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 @@ static void unpack_tar(char *first)
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 @@ static void trim2list(void *list, char *pline)
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 @@ static void do_XT(char **pline, long len)
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 @@ void tar_main(void)
}
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 @@ void tar_main(void)
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 @@ void tar_main(void)
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 @@ void tar_main(void)
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 @@ void tar_main(void)
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 @@ void tar_main(void)
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 @@ void tar_main(void)
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 3fadf3ad..cdb13e2a 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 @@ config TEST
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 @@ static int do_test(char **args, int *count)
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 @@ static int do_test(char **args, int *count)
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 @@ static int do_test(char **args, int *count)
} 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 @@ static int do_test(char **args, int *count)
#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 1becad1b..078aca58 100644
--- a/toys/posix/time.c
+++ b/toys/posix/time.c
@@ -31,7 +31,7 @@ void time_main(void)
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 5e33d7f7..e687ff81 100644
--- a/toys/posix/touch.c
+++ b/toys/posix/touch.c
@@ -71,7 +71,6 @@ void touch_main(void)
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 37970983..642f8871 100644
--- a/toys/posix/ulimit.c
+++ b/toys/posix/ulimit.c
@@ -22,7 +22,6 @@ USE_ULIMIT(OLDTOY(prlimit, ulimit, TOYFLAG_USR|TOYFLAG_BIN))
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 fe44cedd..d11e1e5c 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 @@ void uname_main(void)
}
xputsn(c);
}
+ if (FLAG(p)) xputsn(" unknown"+!needspace);
xputc('\n');
}
diff --git a/toys/posix/uuencode.c b/toys/posix/uuencode.c
index 160954d8..3bede303 100644
--- a/toys/posix/uuencode.c
+++ b/toys/posix/uuencode.c
@@ -24,19 +24,19 @@ void uuencode_main(void)
{
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 @@ void uuencode_main(void)
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 2515af38..24353852 100644
--- a/toys/posix/who.c
+++ b/toys/posix/who.c
@@ -16,7 +16,6 @@ USE_WHO(NEWTOY(who, "a", TOYFLAG_USR|TOYFLAG_BIN))
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 cc3ee3de..67fa3a05 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 @@ void xargs_main(void)
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 014437cb..7d59f661 100644
--- a/www/design.html
+++ b/www/design.html
@@ -401,7 +401,7 @@ effort on them.</p>
<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 @@ openat() family of functions (which take a directory filehandle instead of
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 @@ now we're doing this." (Not a hard and fast rule about _where_ it goes,
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 00000000..84354221
--- /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 00000000..869abbda
--- /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 e6fa6160..d166bad5 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 @@ implementing a
<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 @@ but develops on a standard 64-bit Linux+glibc distro while building embedded
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 @@ runtime memory. (Even more when statically linked.)</p>
<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 @@ installed on the system alongside the static binary:
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 @@ cd musl-cross-make
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 @@ export "PATH=~/musl-cross-make/ccc/m68k-linux-musl-cross/bin:$PATH"<br />
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 @@ Pages</a>.</p>
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 @@ auditable version of the cmdline portion of that base.</p>
<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 @@ this system because 1) you're in a toybox source directory, 2) your cross
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 @@ cd musl-cross-make
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 @@ to the build, by calling the script directly and listing packages on
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 bade8d1b..00000000
--- 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 4acc95a7..922fe3ef 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 cc85450e..c109c7b4 100644
--- a/www/news.html
+++ b/www/news.html
@@ -8,6 +8,608 @@ a development environment. See the links on the left for details.</p>
<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 551eb2eb..7c32b2a7 100644
--- a/www/roadmap.html
+++ b/www/roadmap.html
@@ -131,14 +131,15 @@ val what), fortran support (asa fort77), and batch processing support (batch
qalter qdel qhold qmove qmsg qrerun qrls qselect qsig qstat qsub).</p>
<p>Some commands are for a compiler toolchain (ar c99 cflow ctags cxref gencat
-iconv lex m4 make nm strings strip tsort yacc) which is 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 @@ function, source, declare...)</p>
<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 @@ ignored.</p>
<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 @@ already decided to include, useless for deciding _what_ to include.</p>
<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 @@ egrep expr fdisk find grep gzip head hostname id install ln ls
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 @@ required bash extensions not present in shells such as busybox ash.
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 @@ echo egrep env expr find fuser getconf getopt git grep gzip head hexdump
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 @@ tar diff printf wget rsync fdisk vi less tr test stty fold expr dd
<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 @@ of metadata on top of what came before, until they wind up <a href=https://githu
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 @@ and nobody's quite sure if the license is BSD or GPL. It inexplicably
<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 "kinit" command is another gratuitous rename, it's init running as PID 1.
The halt, poweroff, and reboot commands work with it.</p>
<p>Yet more stale forks of dash and gzip got sucked in here (see "dubious
-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 @@ mtrace nscd rpcent rpcinfo tzselect zdump zic
<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 @@ sum sync tar touch umask umount unalias where
<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 @@ umount waitdev
</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 @@ snapshots mostly consisting of software from the 1990's. For example the
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 @@ ebtables is an ethernet version of iptables (for bridging),
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 @@ rootloader seems to be another reflash daemon but without dhcp.</p>
<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 @@ watchdog
pwgen readelf unicode
rsync
linux32 hd strace
+gpiodetect gpiofind gpioget gpioinfo gpioset httpd uclampset
</span>
</b></blockquote>
@@ -1262,7 +1271,7 @@ libraries. (While toybox contains equivalent functionality to a lot of these
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 @@ library interface.)</p>
<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 @@ util-linux...</p>
(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