aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2022-01-20 12:12:33 -0800
committerElliott Hughes <enh@google.com>2022-01-20 12:52:14 -0800
commite95470fb07c7cf56209ad3042485c324c91b0729 (patch)
tree649cf9f8c345e11369ff685a33a7b6af196408a7
parented6451c5a0d9c76178ed066edbe3d7d65e0a3930 (diff)
parente7e4229c059f4a45eaf0ff0cb0f228275e3e7772 (diff)
downloadtoybox-e95470fb07c7cf56209ad3042485c324c91b0729.tar.gz
Upgrade toybox to e7e4229c059f4a45eaf0ff0cb0f228275e3e7772
Test: make Change-Id: Ie5a3e5de1ef654d46e0f411dabc22adf89bc61fc
-rw-r--r--METADATA8
-rw-r--r--android/device/generated/flags.h26
-rw-r--r--android/device/generated/globals.h31
-rw-r--r--android/device/generated/help.h6
-rw-r--r--android/device/generated/newtoys.h4
-rw-r--r--android/linux/generated/flags.h26
-rw-r--r--android/linux/generated/globals.h31
-rw-r--r--android/linux/generated/help.h6
-rw-r--r--android/linux/generated/newtoys.h4
-rw-r--r--android/mac/generated/flags.h26
-rw-r--r--android/mac/generated/globals.h31
-rw-r--r--android/mac/generated/help.h6
-rw-r--r--android/mac/generated/newtoys.h4
-rwxr-xr-xconfigure11
-rw-r--r--lib/lib.c4
-rw-r--r--lib/lib.h2
-rw-r--r--lib/linestack.c4
-rw-r--r--lib/llist.c11
-rw-r--r--lib/portability.c8
-rw-r--r--lib/tty.c21
-rwxr-xr-xscripts/findglobals.sh2
-rw-r--r--scripts/mkflags.c2
-rwxr-xr-xscripts/mkroot.sh58
-rwxr-xr-xtests/cmp.test32
-rwxr-xr-xtests/fmt.test3
-rwxr-xr-xtests/nl.test3
-rwxr-xr-xtests/sort.test17
-rw-r--r--toys.h5
-rw-r--r--toys/android/README5
-rw-r--r--toys/example/demo_scankey.c16
-rw-r--r--toys/lsb/dmesg.c2
-rw-r--r--toys/net/README7
-rw-r--r--toys/net/host.c196
-rw-r--r--toys/net/ping.c4
-rw-r--r--toys/other/chrt.c3
-rw-r--r--toys/other/clear.c2
-rw-r--r--toys/other/hexedit.c59
-rw-r--r--toys/other/insmod.c2
-rw-r--r--toys/other/ionice.c1
-rw-r--r--toys/other/lsusb.c80
-rw-r--r--toys/other/nsenter.c1
-rw-r--r--toys/other/pivot_root.c3
-rw-r--r--toys/other/pwgen.c2
-rw-r--r--toys/other/readahead.c2
-rw-r--r--toys/other/reset.c5
-rw-r--r--toys/other/rmmod.c1
-rw-r--r--toys/other/taskset.c1
-rw-r--r--toys/other/uclampset.c1
-rw-r--r--toys/pending/README2
-rw-r--r--toys/pending/diff.c12
-rw-r--r--toys/pending/host.c220
-rw-r--r--toys/pending/init.c2
-rw-r--r--toys/pending/modprobe.c1
-rw-r--r--toys/pending/strace.c1
-rw-r--r--toys/pending/vi.c37
-rw-r--r--toys/posix/cmp.c35
-rw-r--r--toys/posix/getconf.c10
-rw-r--r--toys/posix/grep.c10
-rw-r--r--toys/posix/ls.c10
-rw-r--r--toys/posix/nl.c17
-rw-r--r--toys/posix/ps.c17
-rw-r--r--toys/posix/sort.c56
-rw-r--r--toys/posix/time.c27
-rw-r--r--www/doc/ext2.html (renamed from www/ext2.html)0
-rw-r--r--www/doc/mount.html196
-rw-r--r--www/doc/mount.txt163
-rw-r--r--www/news.html2
67 files changed, 837 insertions, 766 deletions
diff --git a/METADATA b/METADATA
index a5797b21..ff87ac55 100644
--- a/METADATA
+++ b/METADATA
@@ -9,11 +9,11 @@ third_party {
type: GIT
value: "https://github.com/landley/toybox"
}
- version: "ea4748a7cbfa5e2f3ef188f917d4e5aeac70dd0f"
+ version: "e7e4229c059f4a45eaf0ff0cb0f228275e3e7772"
license_type: UNENCUMBERED
last_upgrade_date {
- year: 2021
- month: 12
- day: 13
+ year: 2022
+ month: 1
+ day: 20
}
}
diff --git a/android/device/generated/flags.h b/android/device/generated/flags.h
index c2ea833c..a531ad1d 100644
--- a/android/device/generated/flags.h
+++ b/android/device/generated/flags.h
@@ -5,7 +5,7 @@
#define FORCED_FLAGLL 1ULL
#else
#define FORCED_FLAG 0
-#define FORCED_FLAGLL 0
+#define FORCED_FLAGLL 0LL
#endif
// acpi abctV abctV
@@ -352,12 +352,13 @@
#undef FOR_clear
#endif
-// cmp <1>2ls(silent)(quiet)[!ls] <1>2ls(silent)(quiet)[!ls]
+// cmp <1>4ls(silent)(quiet)n#<1[!ls] <1>4ls(silent)(quiet)n#<1[!ls]
#undef OPTSTR_cmp
-#define OPTSTR_cmp "<1>2ls(silent)(quiet)[!ls]"
+#define OPTSTR_cmp "<1>4ls(silent)(quiet)n#<1[!ls]"
#ifdef CLEANUP_cmp
#undef CLEANUP_cmp
#undef FOR_cmp
+#undef FLAG_n
#undef FLAG_s
#undef FLAG_l
#endif
@@ -2124,16 +2125,16 @@
#undef FLAG_n
#endif
-// nl v#=1l#w#<0=6Eb:n:s: v#=1l#w#<0=6Eb:n:s:
+// nl v#=1l#w#<0=6b:n:s:E v#=1l#w#<0=6b:n:s:E
#undef OPTSTR_nl
-#define OPTSTR_nl "v#=1l#w#<0=6Eb:n:s:"
+#define OPTSTR_nl "v#=1l#w#<0=6b:n:s:E"
#ifdef CLEANUP_nl
#undef CLEANUP_nl
#undef FOR_nl
+#undef FLAG_E
#undef FLAG_s
#undef FLAG_n
#undef FLAG_b
-#undef FLAG_E
#undef FLAG_w
#undef FLAG_l
#undef FLAG_v
@@ -3980,8 +3981,9 @@
#ifndef TT
#define TT this.cmp
#endif
-#define FLAG_s (1<<0)
-#define FLAG_l (1<<1)
+#define FLAG_n (1<<0)
+#define FLAG_s (1<<1)
+#define FLAG_l (1<<2)
#endif
#ifdef FOR_comm
@@ -5478,10 +5480,10 @@
#ifndef TT
#define TT this.nl
#endif
-#define FLAG_s (1<<0)
-#define FLAG_n (1<<1)
-#define FLAG_b (1<<2)
-#define FLAG_E (1<<3)
+#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)
diff --git a/android/device/generated/globals.h b/android/device/generated/globals.h
index 68583846..55402400 100644
--- a/android/device/generated/globals.h
+++ b/android/device/generated/globals.h
@@ -151,6 +151,15 @@ struct ftpget_data {
int fd;
};
+// toys/net/host.c
+
+struct host_data {
+ char *t;
+
+ char **nsname;
+ unsigned nslen;
+};
+
// toys/net/ifconfig.c
struct ifconfig_data {
@@ -332,6 +341,12 @@ struct lspci_data {
FILE *db;
};
+// toys/other/lsusb.c
+
+struct lsusb_data {
+ void *ids;
+};
+
// toys/other/makedevs.c
struct makedevs_data {
@@ -741,12 +756,6 @@ struct hexdump_data {
// boundaries if necessesary.
};
-// toys/pending/host.c
-
-struct host_data {
- char *type_str;
-};
-
// toys/pending/ip.c
struct ip_data {
@@ -1197,6 +1206,8 @@ struct cksum_data {
// toys/posix/cmp.c
struct cmp_data {
+ long n;
+
int fd;
char *name;
};
@@ -1393,8 +1404,7 @@ struct nl_data {
long w, l, v;
// Count of consecutive blank lines for -l has to persist between files
- long lcount;
- long slen;
+ long lcount, slen;
};
// toys/posix/od.c
@@ -1495,7 +1505,7 @@ struct sort_data {
char *o, *T, S;
void *key_list;
- int linecount;
+ unsigned linecount;
char **lines, *name;
};
@@ -1633,6 +1643,7 @@ extern union global_union {
struct su_data su;
struct umount_data umount;
struct ftpget_data ftpget;
+ struct host_data host;
struct ifconfig_data ifconfig;
struct microcom_data microcom;
struct netcat_data netcat;
@@ -1657,6 +1668,7 @@ extern union global_union {
struct losetup_data losetup;
struct lsattr_data lsattr;
struct lspci_data lspci;
+ struct lsusb_data lsusb;
struct makedevs_data makedevs;
struct mix_data mix;
struct mkpasswd_data mkpasswd;
@@ -1704,7 +1716,6 @@ extern union global_union {
struct getty_data getty;
struct groupadd_data groupadd;
struct hexdump_data hexdump;
- struct host_data host;
struct ip_data ip;
struct ipcrm_data ipcrm;
struct ipcs_data ipcs;
diff --git a/android/device/generated/help.h b/android/device/generated/help.h
index fd6c90f6..bf561d09 100644
--- a/android/device/generated/help.h
+++ b/android/device/generated/help.h
@@ -128,6 +128,8 @@
#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)\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_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"
#define HELP_ftpget "usage: ftpget [-cvgslLmMdD] [-P PORT] [-p PASSWORD] [-u USER] HOST [LOCAL] REMOTE\n\nTalk to ftp server. By default get REMOTE file via passive anonymous\ntransfer, optionally saving under a LOCAL name. Can also send, list, etc.\n\n-c Continue partial transfer\n-p Use PORT instead of \"21\"\n-P Use PASSWORD instead of \"ftpget@\"\n-u Use USER instead of \"anonymous\"\n-v Verbose\n\nWays to interact with FTP server:\n-d Delete file\n-D Remove directory\n-g Get file (default)\n-l List directory\n-L List (filenames only)\n-m Move file on server from LOCAL to REMOTE\n-M mkdir\n-s Send file"
@@ -436,8 +438,6 @@
#define HELP_init "usage: init\n\nSystem V style init.\n\nFirst program to run (as PID 1) when the system comes up, reading\n/etc/inittab to determine actions."
-#define HELP_host "usage: host [-av] [-t TYPE] NAME [SERVER]\n\nPerform DNS lookup on NAME, which can be a domain name to lookup,\nor an IPv4 dotted or IPv6 colon-separated address to reverse lookup.\nSERVER (if present) is the DNS server to use.\n\n-a -v -t ANY\n-t TYPE query records of type TYPE\n-v verbose"
-
#define HELP_hd "usage: hd [FILE...]\n\nDisplay file(s) in cannonical hex+ASCII format."
#define HELP_hexdump "usage: hexdump [-bcCdovx] [-n LEN] [-s SKIP] [FILE...]\n\nDump file(s) in hexadecimal format.\n\n-n LEN Show LEN bytes of output\n-s SKIP Skip bytes of input\n-v Verbose (don't combine identical lines)\n\nDisplay type:\n-b One byte octal -c One byte character -C Canonical (hex + ASCII)\n-d Two byte decimal -o Two byte octal -x Two byte hexadecimal (default)"
@@ -634,7 +634,7 @@
#define HELP_comm "usage: comm [-123] FILE1 FILE2\n\nRead FILE1 and FILE2, which should be ordered, and produce three text\ncolumns as output: lines only in FILE1; lines only in FILE2; and lines\nin both files. Filename \"-\" is a synonym for stdin.\n\n-1 Suppress the output column of lines unique to FILE1\n-2 Suppress the output column of lines unique to FILE2\n-3 Suppress the output column of lines duplicated in FILE1 and FILE2"
-#define HELP_cmp "usage: cmp [-l] [-s] FILE1 [FILE2 [SKIP1 [SKIP2]]]\n\nCompare the contents of two files. (Or stdin and file if only one given.)\n\n-l Show all differing bytes\n-s Silent"
+#define HELP_cmp "usage: cmp [-ls] [-n LEN] FILE1 [FILE2 [SKIP1 [SKIP2]]]\n\nCompare the contents of files (vs stdin if only one given), optionally\nskipping bytes at start.\n\n-l Show all differing bytes\n-n LEN Compare at most LEN bytes\n-s Silent"
#define HELP_crc32 "usage: crc32 [file...]\n\nOutput crc32 checksum for each file."
diff --git a/android/device/generated/newtoys.h b/android/device/generated/newtoys.h
index 10ac6cc3..cebac157 100644
--- a/android/device/generated/newtoys.h
+++ b/android/device/generated/newtoys.h
@@ -39,7 +39,7 @@ USE_CHSH(NEWTOY(chsh, "s:", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
USE_CHVT(NEWTOY(chvt, "<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>2ls(silent)(quiet)[!ls]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
+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))
@@ -190,7 +190,7 @@ 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_NETSTAT(NEWTOY(netstat, "pWrxwutneal", TOYFLAG_BIN))
USE_NICE(NEWTOY(nice, "^<1n#", TOYFLAG_BIN))
-USE_NL(NEWTOY(nl, "v#=1l#w#<0=6Eb:n:s:", TOYFLAG_USR|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))
diff --git a/android/linux/generated/flags.h b/android/linux/generated/flags.h
index ffb2c68a..bd74c4a9 100644
--- a/android/linux/generated/flags.h
+++ b/android/linux/generated/flags.h
@@ -5,7 +5,7 @@
#define FORCED_FLAGLL 1ULL
#else
#define FORCED_FLAG 0
-#define FORCED_FLAGLL 0
+#define FORCED_FLAGLL 0LL
#endif
// acpi abctV
@@ -352,12 +352,13 @@
#undef FOR_clear
#endif
-// cmp <1>2ls(silent)(quiet)[!ls] <1>2ls(silent)(quiet)[!ls]
+// cmp <1>4ls(silent)(quiet)n#<1[!ls] <1>4ls(silent)(quiet)n#<1[!ls]
#undef OPTSTR_cmp
-#define OPTSTR_cmp "<1>2ls(silent)(quiet)[!ls]"
+#define OPTSTR_cmp "<1>4ls(silent)(quiet)n#<1[!ls]"
#ifdef CLEANUP_cmp
#undef CLEANUP_cmp
#undef FOR_cmp
+#undef FLAG_n
#undef FLAG_s
#undef FLAG_l
#endif
@@ -2124,16 +2125,16 @@
#undef FLAG_n
#endif
-// nl v#=1l#w#<0=6Eb:n:s: v#=1l#w#<0=6Eb:n:s:
+// nl v#=1l#w#<0=6b:n:s:E v#=1l#w#<0=6b:n:s:E
#undef OPTSTR_nl
-#define OPTSTR_nl "v#=1l#w#<0=6Eb:n:s:"
+#define OPTSTR_nl "v#=1l#w#<0=6b:n:s:E"
#ifdef CLEANUP_nl
#undef CLEANUP_nl
#undef FOR_nl
+#undef FLAG_E
#undef FLAG_s
#undef FLAG_n
#undef FLAG_b
-#undef FLAG_E
#undef FLAG_w
#undef FLAG_l
#undef FLAG_v
@@ -3980,8 +3981,9 @@
#ifndef TT
#define TT this.cmp
#endif
-#define FLAG_s (1<<0)
-#define FLAG_l (1<<1)
+#define FLAG_n (1<<0)
+#define FLAG_s (1<<1)
+#define FLAG_l (1<<2)
#endif
#ifdef FOR_comm
@@ -5478,10 +5480,10 @@
#ifndef TT
#define TT this.nl
#endif
-#define FLAG_s (1<<0)
-#define FLAG_n (1<<1)
-#define FLAG_b (1<<2)
-#define FLAG_E (1<<3)
+#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)
diff --git a/android/linux/generated/globals.h b/android/linux/generated/globals.h
index 68583846..55402400 100644
--- a/android/linux/generated/globals.h
+++ b/android/linux/generated/globals.h
@@ -151,6 +151,15 @@ struct ftpget_data {
int fd;
};
+// toys/net/host.c
+
+struct host_data {
+ char *t;
+
+ char **nsname;
+ unsigned nslen;
+};
+
// toys/net/ifconfig.c
struct ifconfig_data {
@@ -332,6 +341,12 @@ struct lspci_data {
FILE *db;
};
+// toys/other/lsusb.c
+
+struct lsusb_data {
+ void *ids;
+};
+
// toys/other/makedevs.c
struct makedevs_data {
@@ -741,12 +756,6 @@ struct hexdump_data {
// boundaries if necessesary.
};
-// toys/pending/host.c
-
-struct host_data {
- char *type_str;
-};
-
// toys/pending/ip.c
struct ip_data {
@@ -1197,6 +1206,8 @@ struct cksum_data {
// toys/posix/cmp.c
struct cmp_data {
+ long n;
+
int fd;
char *name;
};
@@ -1393,8 +1404,7 @@ struct nl_data {
long w, l, v;
// Count of consecutive blank lines for -l has to persist between files
- long lcount;
- long slen;
+ long lcount, slen;
};
// toys/posix/od.c
@@ -1495,7 +1505,7 @@ struct sort_data {
char *o, *T, S;
void *key_list;
- int linecount;
+ unsigned linecount;
char **lines, *name;
};
@@ -1633,6 +1643,7 @@ extern union global_union {
struct su_data su;
struct umount_data umount;
struct ftpget_data ftpget;
+ struct host_data host;
struct ifconfig_data ifconfig;
struct microcom_data microcom;
struct netcat_data netcat;
@@ -1657,6 +1668,7 @@ extern union global_union {
struct losetup_data losetup;
struct lsattr_data lsattr;
struct lspci_data lspci;
+ struct lsusb_data lsusb;
struct makedevs_data makedevs;
struct mix_data mix;
struct mkpasswd_data mkpasswd;
@@ -1704,7 +1716,6 @@ extern union global_union {
struct getty_data getty;
struct groupadd_data groupadd;
struct hexdump_data hexdump;
- struct host_data host;
struct ip_data ip;
struct ipcrm_data ipcrm;
struct ipcs_data ipcs;
diff --git a/android/linux/generated/help.h b/android/linux/generated/help.h
index a1aa88a2..9ae1e48e 100644
--- a/android/linux/generated/help.h
+++ b/android/linux/generated/help.h
@@ -130,6 +130,8 @@
#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)\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_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"
#define HELP_ftpget "usage: ftpget [-cvgslLmMdD] [-P PORT] [-p PASSWORD] [-u USER] HOST [LOCAL] REMOTE\n\nTalk to ftp server. By default get REMOTE file via passive anonymous\ntransfer, optionally saving under a LOCAL name. Can also send, list, etc.\n\n-c Continue partial transfer\n-p Use PORT instead of \"21\"\n-P Use PASSWORD instead of \"ftpget@\"\n-u Use USER instead of \"anonymous\"\n-v Verbose\n\nWays to interact with FTP server:\n-d Delete file\n-D Remove directory\n-g Get file (default)\n-l List directory\n-L List (filenames only)\n-m Move file on server from LOCAL to REMOTE\n-M mkdir\n-s Send file"
@@ -438,8 +440,6 @@
#define HELP_init "usage: init\n\nSystem V style init.\n\nFirst program to run (as PID 1) when the system comes up, reading\n/etc/inittab to determine actions."
-#define HELP_host "usage: host [-av] [-t TYPE] NAME [SERVER]\n\nPerform DNS lookup on NAME, which can be a domain name to lookup,\nor an IPv4 dotted or IPv6 colon-separated address to reverse lookup.\nSERVER (if present) is the DNS server to use.\n\n-a -v -t ANY\n-t TYPE query records of type TYPE\n-v verbose"
-
#define HELP_hd "usage: hd [FILE...]\n\nDisplay file(s) in cannonical hex+ASCII format."
#define HELP_hexdump "usage: hexdump [-bcCdovx] [-n LEN] [-s SKIP] [FILE...]\n\nDump file(s) in hexadecimal format.\n\n-n LEN Show LEN bytes of output\n-s SKIP Skip bytes of input\n-v Verbose (don't combine identical lines)\n\nDisplay type:\n-b One byte octal -c One byte character -C Canonical (hex + ASCII)\n-d Two byte decimal -o Two byte octal -x Two byte hexadecimal (default)"
@@ -640,7 +640,7 @@
#define HELP_comm "usage: comm [-123] FILE1 FILE2\n\nRead FILE1 and FILE2, which should be ordered, and produce three text\ncolumns as output: lines only in FILE1; lines only in FILE2; and lines\nin both files. Filename \"-\" is a synonym for stdin.\n\n-1 Suppress the output column of lines unique to FILE1\n-2 Suppress the output column of lines unique to FILE2\n-3 Suppress the output column of lines duplicated in FILE1 and FILE2"
-#define HELP_cmp "usage: cmp [-l] [-s] FILE1 [FILE2 [SKIP1 [SKIP2]]]\n\nCompare the contents of two files. (Or stdin and file if only one given.)\n\n-l Show all differing bytes\n-s Silent"
+#define HELP_cmp "usage: cmp [-ls] [-n LEN] FILE1 [FILE2 [SKIP1 [SKIP2]]]\n\nCompare the contents of files (vs stdin if only one given), optionally\nskipping bytes at start.\n\n-l Show all differing bytes\n-n LEN Compare at most LEN bytes\n-s Silent"
#define HELP_crc32 "usage: crc32 [file...]\n\nOutput crc32 checksum for each file."
diff --git a/android/linux/generated/newtoys.h b/android/linux/generated/newtoys.h
index 10ac6cc3..cebac157 100644
--- a/android/linux/generated/newtoys.h
+++ b/android/linux/generated/newtoys.h
@@ -39,7 +39,7 @@ USE_CHSH(NEWTOY(chsh, "s:", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
USE_CHVT(NEWTOY(chvt, "<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>2ls(silent)(quiet)[!ls]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
+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))
@@ -190,7 +190,7 @@ 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_NETSTAT(NEWTOY(netstat, "pWrxwutneal", TOYFLAG_BIN))
USE_NICE(NEWTOY(nice, "^<1n#", TOYFLAG_BIN))
-USE_NL(NEWTOY(nl, "v#=1l#w#<0=6Eb:n:s:", TOYFLAG_USR|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))
diff --git a/android/mac/generated/flags.h b/android/mac/generated/flags.h
index c065fe2e..967f0f45 100644
--- a/android/mac/generated/flags.h
+++ b/android/mac/generated/flags.h
@@ -5,7 +5,7 @@
#define FORCED_FLAGLL 1ULL
#else
#define FORCED_FLAG 0
-#define FORCED_FLAGLL 0
+#define FORCED_FLAGLL 0LL
#endif
// acpi abctV
@@ -352,12 +352,13 @@
#undef FOR_clear
#endif
-// cmp <1>2ls(silent)(quiet)[!ls] <1>2ls(silent)(quiet)[!ls]
+// cmp <1>4ls(silent)(quiet)n#<1[!ls] <1>4ls(silent)(quiet)n#<1[!ls]
#undef OPTSTR_cmp
-#define OPTSTR_cmp "<1>2ls(silent)(quiet)[!ls]"
+#define OPTSTR_cmp "<1>4ls(silent)(quiet)n#<1[!ls]"
#ifdef CLEANUP_cmp
#undef CLEANUP_cmp
#undef FOR_cmp
+#undef FLAG_n
#undef FLAG_s
#undef FLAG_l
#endif
@@ -2124,16 +2125,16 @@
#undef FLAG_n
#endif
-// nl v#=1l#w#<0=6Eb:n:s: v#=1l#w#<0=6Eb:n:s:
+// nl v#=1l#w#<0=6b:n:s:E v#=1l#w#<0=6b:n:s:E
#undef OPTSTR_nl
-#define OPTSTR_nl "v#=1l#w#<0=6Eb:n:s:"
+#define OPTSTR_nl "v#=1l#w#<0=6b:n:s:E"
#ifdef CLEANUP_nl
#undef CLEANUP_nl
#undef FOR_nl
+#undef FLAG_E
#undef FLAG_s
#undef FLAG_n
#undef FLAG_b
-#undef FLAG_E
#undef FLAG_w
#undef FLAG_l
#undef FLAG_v
@@ -3980,8 +3981,9 @@
#ifndef TT
#define TT this.cmp
#endif
-#define FLAG_s (1<<0)
-#define FLAG_l (1<<1)
+#define FLAG_n (1<<0)
+#define FLAG_s (1<<1)
+#define FLAG_l (1<<2)
#endif
#ifdef FOR_comm
@@ -5478,10 +5480,10 @@
#ifndef TT
#define TT this.nl
#endif
-#define FLAG_s (1<<0)
-#define FLAG_n (1<<1)
-#define FLAG_b (1<<2)
-#define FLAG_E (1<<3)
+#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)
diff --git a/android/mac/generated/globals.h b/android/mac/generated/globals.h
index 68583846..55402400 100644
--- a/android/mac/generated/globals.h
+++ b/android/mac/generated/globals.h
@@ -151,6 +151,15 @@ struct ftpget_data {
int fd;
};
+// toys/net/host.c
+
+struct host_data {
+ char *t;
+
+ char **nsname;
+ unsigned nslen;
+};
+
// toys/net/ifconfig.c
struct ifconfig_data {
@@ -332,6 +341,12 @@ struct lspci_data {
FILE *db;
};
+// toys/other/lsusb.c
+
+struct lsusb_data {
+ void *ids;
+};
+
// toys/other/makedevs.c
struct makedevs_data {
@@ -741,12 +756,6 @@ struct hexdump_data {
// boundaries if necessesary.
};
-// toys/pending/host.c
-
-struct host_data {
- char *type_str;
-};
-
// toys/pending/ip.c
struct ip_data {
@@ -1197,6 +1206,8 @@ struct cksum_data {
// toys/posix/cmp.c
struct cmp_data {
+ long n;
+
int fd;
char *name;
};
@@ -1393,8 +1404,7 @@ struct nl_data {
long w, l, v;
// Count of consecutive blank lines for -l has to persist between files
- long lcount;
- long slen;
+ long lcount, slen;
};
// toys/posix/od.c
@@ -1495,7 +1505,7 @@ struct sort_data {
char *o, *T, S;
void *key_list;
- int linecount;
+ unsigned linecount;
char **lines, *name;
};
@@ -1633,6 +1643,7 @@ extern union global_union {
struct su_data su;
struct umount_data umount;
struct ftpget_data ftpget;
+ struct host_data host;
struct ifconfig_data ifconfig;
struct microcom_data microcom;
struct netcat_data netcat;
@@ -1657,6 +1668,7 @@ extern union global_union {
struct losetup_data losetup;
struct lsattr_data lsattr;
struct lspci_data lspci;
+ struct lsusb_data lsusb;
struct makedevs_data makedevs;
struct mix_data mix;
struct mkpasswd_data mkpasswd;
@@ -1704,7 +1716,6 @@ extern union global_union {
struct getty_data getty;
struct groupadd_data groupadd;
struct hexdump_data hexdump;
- struct host_data host;
struct ip_data ip;
struct ipcrm_data ipcrm;
struct ipcs_data ipcs;
diff --git a/android/mac/generated/help.h b/android/mac/generated/help.h
index a1aa88a2..9ae1e48e 100644
--- a/android/mac/generated/help.h
+++ b/android/mac/generated/help.h
@@ -130,6 +130,8 @@
#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)\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_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"
#define HELP_ftpget "usage: ftpget [-cvgslLmMdD] [-P PORT] [-p PASSWORD] [-u USER] HOST [LOCAL] REMOTE\n\nTalk to ftp server. By default get REMOTE file via passive anonymous\ntransfer, optionally saving under a LOCAL name. Can also send, list, etc.\n\n-c Continue partial transfer\n-p Use PORT instead of \"21\"\n-P Use PASSWORD instead of \"ftpget@\"\n-u Use USER instead of \"anonymous\"\n-v Verbose\n\nWays to interact with FTP server:\n-d Delete file\n-D Remove directory\n-g Get file (default)\n-l List directory\n-L List (filenames only)\n-m Move file on server from LOCAL to REMOTE\n-M mkdir\n-s Send file"
@@ -438,8 +440,6 @@
#define HELP_init "usage: init\n\nSystem V style init.\n\nFirst program to run (as PID 1) when the system comes up, reading\n/etc/inittab to determine actions."
-#define HELP_host "usage: host [-av] [-t TYPE] NAME [SERVER]\n\nPerform DNS lookup on NAME, which can be a domain name to lookup,\nor an IPv4 dotted or IPv6 colon-separated address to reverse lookup.\nSERVER (if present) is the DNS server to use.\n\n-a -v -t ANY\n-t TYPE query records of type TYPE\n-v verbose"
-
#define HELP_hd "usage: hd [FILE...]\n\nDisplay file(s) in cannonical hex+ASCII format."
#define HELP_hexdump "usage: hexdump [-bcCdovx] [-n LEN] [-s SKIP] [FILE...]\n\nDump file(s) in hexadecimal format.\n\n-n LEN Show LEN bytes of output\n-s SKIP Skip bytes of input\n-v Verbose (don't combine identical lines)\n\nDisplay type:\n-b One byte octal -c One byte character -C Canonical (hex + ASCII)\n-d Two byte decimal -o Two byte octal -x Two byte hexadecimal (default)"
@@ -640,7 +640,7 @@
#define HELP_comm "usage: comm [-123] FILE1 FILE2\n\nRead FILE1 and FILE2, which should be ordered, and produce three text\ncolumns as output: lines only in FILE1; lines only in FILE2; and lines\nin both files. Filename \"-\" is a synonym for stdin.\n\n-1 Suppress the output column of lines unique to FILE1\n-2 Suppress the output column of lines unique to FILE2\n-3 Suppress the output column of lines duplicated in FILE1 and FILE2"
-#define HELP_cmp "usage: cmp [-l] [-s] FILE1 [FILE2 [SKIP1 [SKIP2]]]\n\nCompare the contents of two files. (Or stdin and file if only one given.)\n\n-l Show all differing bytes\n-s Silent"
+#define HELP_cmp "usage: cmp [-ls] [-n LEN] FILE1 [FILE2 [SKIP1 [SKIP2]]]\n\nCompare the contents of files (vs stdin if only one given), optionally\nskipping bytes at start.\n\n-l Show all differing bytes\n-n LEN Compare at most LEN bytes\n-s Silent"
#define HELP_crc32 "usage: crc32 [file...]\n\nOutput crc32 checksum for each file."
diff --git a/android/mac/generated/newtoys.h b/android/mac/generated/newtoys.h
index 10ac6cc3..cebac157 100644
--- a/android/mac/generated/newtoys.h
+++ b/android/mac/generated/newtoys.h
@@ -39,7 +39,7 @@ USE_CHSH(NEWTOY(chsh, "s:", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
USE_CHVT(NEWTOY(chvt, "<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>2ls(silent)(quiet)[!ls]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
+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))
@@ -190,7 +190,7 @@ 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_NETSTAT(NEWTOY(netstat, "pWrxwutneal", TOYFLAG_BIN))
USE_NICE(NEWTOY(nice, "^<1n#", TOYFLAG_BIN))
-USE_NL(NEWTOY(nl, "v#=1l#w#<0=6Eb:n:s:", TOYFLAG_USR|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))
diff --git a/configure b/configure
index effba7d0..af8e1134 100755
--- a/configure
+++ b/configure
@@ -13,7 +13,7 @@ fi
# CFLAGS and OPTIMIZE are different so you can add extra CFLAGS without
# disabling default optimizations
-[ -z "$CFLAGS" ] && CFLAGS="-Wall -Wundef -Wno-char-subscripts -Werror=implicit-function-declaration"
+[ -z "$CFLAGS" ] && CFLAGS="-Wall -Wundef -Wno-char-subscripts -Werror=implicit-function-declaration -Wno-pointer-sign"
# Required for our expected ABI. we're 8-bit clean thus "char" must be unsigned.
CFLAGS="$CFLAGS -funsigned-char"
[ -z "$OPTIMIZE" ] && OPTIMIZE="-Os -ffunction-sections -fdata-sections -fno-asynchronous-unwind-tables -fno-strict-aliasing"
@@ -33,7 +33,14 @@ fi
# you call scripts/make.sh and friends directly.
[ -z "$CC" ] && CC=cc
-[ -z "$STRIP" ] && STRIP="strip -s -R .note* -R .comment"
+
+# Strip harder on Linux.
+# Darwin's strip doesn't have equivalents of the binutils -s or -R.
+[ -z "$STRIP" ] && STRIP=strip
+if [ "$(uname)" != "Darwin" ]
+then
+ [ -z "$STRIP" ] && STRIP="strip -s -R .note* -R .comment"
+fi
# If HOSTCC needs CFLAGS or LDFLAGS, just add them to the variable
# ala HOSTCC="blah-cc --static"
diff --git a/lib/lib.c b/lib/lib.c
index b219a5d5..84af3f48 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -457,7 +457,7 @@ char *chomp(char *s)
int unescape(char c)
{
- char *from = "\\abefnrtv", *to = "\\\a\b\033\f\n\r\t\v";
+ char *from = "\\abefnrtv", *to = "\\\a\b\e\f\n\r\t\v";
int idx = stridx(from, c);
return (idx == -1) ? 0 : to[idx];
@@ -483,7 +483,7 @@ int unescape2(char **c, int echo)
if (-1 == (idx = stridx("\\abeEfnrtv'\"?0", **c))) return '\\';
++*c;
- return "\\\a\b\033\033\f\n\r\t\v'\"?"[idx];
+ return "\\\a\b\e\e\f\n\r\t\v'\"?"[idx];
}
// If string ends with suffix return pointer to start of suffix in string,
diff --git a/lib/lib.h b/lib/lib.h
index 3880d799..16255da8 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -348,8 +348,6 @@ int scan_key_getsize(char *scratch, int timeout_ms, unsigned *xx, unsigned *yy);
void xsetspeed(struct termios *tio, int speed);
int set_terminal(int fd, int raw, int speed, struct termios *old);
void xset_terminal(int fd, int raw, int speed, struct termios *old);
-void tty_esc(char *s);
-void tty_jump(int x, int y);
void tty_reset(void);
void tty_sigreset(int i);
void start_redraw(unsigned *width, unsigned *height);
diff --git a/lib/linestack.c b/lib/linestack.c
index e6ae1b57..47eb2af9 100644
--- a/lib/linestack.c
+++ b/lib/linestack.c
@@ -142,9 +142,9 @@ int crunch_rev_escape(FILE *out, int cols, int wc)
{
int rc;
- tty_esc("7m");
+ xputsn("\e[7m");
rc = crunch_escape(out, cols, wc);
- tty_esc("27m");
+ xputsn("\e[27m");
return rc;
}
diff --git a/lib/llist.c b/lib/llist.c
index e82cb954..6ceb1ce7 100644
--- a/lib/llist.c
+++ b/lib/llist.c
@@ -41,14 +41,13 @@ void llist_traverse(void *list, void (*using)(void *node))
// as &list)
void *llist_pop(void *list)
{
- // I'd use a void ** for the argument, and even accept the typecast in all
- // callers as documentation you need the &, except the stupid compiler
- // would then scream about type-punned pointers. Screw it.
- void **llist = (void **)list;
- void **next = (void **)*llist;
+ void **llist = list, **next;
+
+ if (!list || !*llist) return 0;
+ next = (void **)*llist;
*llist = *next;
- return (void *)next;
+ return next;
}
// Remove first item from &list and return it
diff --git a/lib/portability.c b/lib/portability.c
index cd917bc9..5f98138c 100644
--- a/lib/portability.c
+++ b/lib/portability.c
@@ -457,7 +457,6 @@ static const struct signame signames[] = {
// Non-POSIX signals that don't cause termination
SIGNIFY(WINCH),
};
-int signames_len = ARRAY_LEN(signames);
#undef SIGNIFY
@@ -465,7 +464,6 @@ void xsignal_all_killers(void *handler)
{
int i;
- if (!handler) handler = SIG_DFL;
for (i = 1; signames[i].num != SIGCHLD; i++)
if (signames[i].num != SIGKILL) xsignal(signames[i].num, handler);
}
@@ -477,8 +475,8 @@ int sig_to_num(char *sigstr)
char *s;
// Numeric?
- i = estrtol(sigstr, &s, 10);
- if (!errno && !*s) return i;
+ offset = estrtol(sigstr, &s, 10);
+ if (!errno && !*s) return offset;
// Skip leading "SIG".
strcasestart(&sigstr, "sig");
@@ -512,7 +510,7 @@ char *num_to_sig(int sig)
int i;
// A named signal?
- for (i=0; i<signames_len; i++)
+ for (i=0; i<ARRAY_LEN(signames); i++)
if (signames[i].num == sig) return signames[i].name;
// A real-time signal?
diff --git a/lib/tty.c b/lib/tty.c
index e5e3d41e..b4aee45e 100644
--- a/lib/tty.c
+++ b/lib/tty.c
@@ -252,27 +252,10 @@ int scan_key(char *scratch, int timeout_ms)
return scan_key_getsize(scratch, timeout_ms, NULL, NULL);
}
-void tty_esc(char *s)
-{
- printf("\e[%s", s);
-}
-
-void tty_jump(int x, int y)
-{
- char s[32];
-
- sprintf(s, "%d;%dH", y+1, x+1);
- tty_esc(s);
-}
-
void tty_reset(void)
{
set_terminal(0, 0, 0, 0);
- tty_esc("?25h");
- tty_esc("0m");
- tty_jump(0, 999);
- tty_esc("K");
- fflush(0);
+ xputsn("\e[?25h\e[0m\e[999H\e[K");
}
// If you call set_terminal(), use sigatexit(tty_sigreset);
@@ -296,5 +279,5 @@ void start_redraw(unsigned *width, unsigned *height)
toys.signal = -1;
terminal_probesize(width, height);
}
- xprintf("\033[H\033[J");
+ xputsn("\e[H\e[J");
}
diff --git a/scripts/findglobals.sh b/scripts/findglobals.sh
index 2c63164b..2bb94d69 100755
--- a/scripts/findglobals.sh
+++ b/scripts/findglobals.sh
@@ -3,4 +3,4 @@
# Quick and dirty check to see if anybody's leaked global variables.
# We should have this, toy_list, toybuf, and toys.
-nm toybox_unstripped | grep '[0-9A-Fa-f]* [BCDGRS]' | cut -d ' ' -f 3
+nm --size-sort generated/unstripped/toybox | grep '[0-9A-Fa-f]* [BCDGRS]' #| cut -d ' ' -f 3
diff --git a/scripts/mkflags.c b/scripts/mkflags.c
index 7ea8770d..63f54cd9 100644
--- a/scripts/mkflags.c
+++ b/scripts/mkflags.c
@@ -166,7 +166,7 @@ int main(int argc, char *argv[])
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 0\n#endif\n\n");
+ "#else\n#define FORCED_FLAG 0\n#define FORCED_FLAGLL 0LL\n#endif\n\n");
for (;;) {
struct flag *flist, *aflist, *offlist;
diff --git a/scripts/mkroot.sh b/scripts/mkroot.sh
index 69246950..8a0582df 100755
--- a/scripts/mkroot.sh
+++ b/scripts/mkroot.sh
@@ -1,9 +1,6 @@
#!/bin/bash
-# ----- Setup environment
-
-die() { echo "$@" >&2; exit 1; }
-announce() { echo -e "\033]2;$CROSS $*\007\n=== $*"; }
+# ------------------------------ 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" \
@@ -18,53 +15,61 @@ done
: ${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
- for i in $TARGETS; do # loop calling ourselves for each target
+
+ 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
- if [ -e "$CROSS_COMPILE" ]; then
- CROSS_COMPILE="${CROSS_COMPILE%cc}" # keep prefix for cc/ld/as/nm/strip...
- else
- echo $TARGETS && exit # list available targets
- fi
+ [ ! -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 compiler works
+# 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"
-# Set CROSS=host if not cross compiling, and create per-target output directory
+# When not cross compiling set CROSS=host. Create per-target output directory
: ${CROSS:=host} ${OUTPUT:=$TOP/$CROSS}
-# ----- Build airlock (Optional)
+# ----- Create hermetic build environment
if [ -z "$NOAIRLOCK"] && [ -n "$CROSS_COMPILE" ]; then
- # When cross compiling set host $PATH to binaries with known behavior
+ # 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 &&
+ 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" &&
-mkdir -p "$OUTPUT" "$LOG" || exit 1
+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
@@ -72,7 +77,8 @@ if [ -z "$NOLOGPATH" ]; then
CROSS_COMPILE=${CROSS_COMPILE##*/}
export WRAPDIR="$BUILD/record-commands" LOGPATH="$LOG/$CROSS-commands.txt"
rm -rf "$WRAPDIR" "$LOGPATH" generated/obj &&
- WRAPDIR="$WRAPDIR" CROSS_COMPILE= source scripts/record-commands || exit 1
+ WRAPDIR="$WRAPDIR" CROSS_COMPILE= NOSTRIP=1 source scripts/record-commands ||
+ exit 1
fi
# Start logging stdout/stderr
@@ -80,6 +86,8 @@ 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...
@@ -103,6 +111,7 @@ fi
mountpoint -q 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
@@ -115,7 +124,7 @@ if [ $$ -eq 1 ]; then # Setup networking for QEMU (needs /proc)
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 Type exit when done.
+ [ -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
@@ -146,6 +155,8 @@ 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
@@ -175,7 +186,7 @@ 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
+ 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
@@ -228,8 +239,7 @@ CONFIG_CMDLINE="console=ttyUL0 earlycon"' BUILTIN=1
echo qemu-system-"$QEMU" '"$@"' $QEMU_MORE -nographic -no-reboot -m 256 \
-kernel $(basename $VMLINUX) $INITRD \
"-append \"panic=1 HOST=$TARGET console=$KARGS \$KARGS\"" \
- ${DTB:+-dtb "$(basename "$DTB")"} ";echo -e '\e[?7h'" \
- > "$OUTPUT/qemu-$TARGET.sh" &&
+ ${DTB:+-dtb "$(basename "$DTB")"} > "$OUTPUT/qemu-$TARGET.sh" &&
chmod +x "$OUTPUT/qemu-$TARGET.sh" || exit 1
fi
@@ -276,5 +286,5 @@ if [ -z "$BUILTIN" ]; then
| gzip) > "$OUTPUT/$CROSS"root.cpio.gz || exit 1
fi
-mv "$LOG/$CROSS".{n,y} #2>/dev/null
+mv "$LOG/$CROSS".{n,y}
rmdir "$MYBUILD" "$BUILD" 2>/dev/null || exit 0 # remove if empty, not an error
diff --git a/tests/cmp.test b/tests/cmp.test
index d1a8033b..ce776e8e 100755
--- a/tests/cmp.test
+++ b/tests/cmp.test
@@ -3,13 +3,13 @@
[ -f testing.sh ] && . testing.sh
# TODO: coreutils cmp uses stdin if only one file is given
-testing "one argument match" 'cmp input && echo yes' "yes\n" \
+testcmd "one argument match" 'input && echo yes' "yes\n" \
"one\ntwo\nthree" "one\ntwo\nthree"
# posix says ""%s %s differ: char %d, line %d\n" but diffutils says "byte"
-testing "one argument diff" 'cmp input | sed s/byte/char/' \
+testcmd "one argument diff" 'input | sed s/byte/char/' \
"input - differ: char 5, line 2\n" "one\ntwo\nthree" "one\nboing\nthree"
-testing "missing file1 [fail]" 'cmp file1 input 2>/dev/null || echo $?' "2\n" "foo" ""
+testcmd "missing file1 [fail]" 'file1 input 2>/dev/null || echo $?' "2\n" "foo" ""
#mkdir dir
#testing "directory [fail]" "cmp dir dir 2>/dev/null || echo yes" \
@@ -19,27 +19,27 @@ testing "missing file1 [fail]" 'cmp file1 input 2>/dev/null || echo $?' "2\n" "f
echo "ab
c" > input2
-testing "identical files, stdout" "cmp input input2" "" "ab\nc\n" ""
-testing "identical files, return code" "cmp input input2 && echo yes" "yes\n" "ab\nc\n" ""
+testcmd "identical files, stdout" "input input2" "" "ab\nc\n" ""
+testcmd "identical files, return code" "input input2 && echo yes" "yes\n" "ab\nc\n" ""
-testing "EOF, stderr" "cmp input input2 2>&1" "cmp: EOF on input2\n" "ab\nc\nx" ""
-testing "EOF, return code" "cmp input input2 2>/dev/null || echo yes" "yes\n" "ab\nc\nx" ""
+testcmd "EOF, stderr" "input input2 2>&1" "cmp: EOF on input2\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.
-testing "diff, stdout" "cmp input input2 | sed s/byte/char/" \
+testcmd "diff, stdout" "input input2 | sed s/byte/char/" \
"input input2 differ: char 4, line 2\n" "ab\nx\nx" ""
-testing "diff, return code" "cmp input input2 > /dev/null || echo yes" "yes\n" "ab\nx\nx" ""
+testcmd "diff, return code" "input input2 > /dev/null || echo yes" "yes\n" "ab\nx\nx" ""
-testing "-s EOF, return code" "cmp -s input input2 2>&1 || echo yes" "yes\n" "ab\nc\nx" ""
-testing "-s diff, return code" "cmp -s input input2 2>&1 || echo yes" "yes\n" "ab\nx\nx" ""
+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" ""
-testing "-l EOF, stderr" "cmp -l input input2 2>&1" "cmp: EOF on input2\n" "ab\nc\nx" ""
-testing "-l diff and EOF, stdout and stderr" "cmp -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\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" ""
-testing "-s not exist" "cmp -s input doesnotexist 2>&1 || echo yes" "yes\n" "x" ""
+testcmd "-s not exist" "-s input doesnotexist 2>&1 || echo yes" "yes\n" "x" ""
rm input2
-testing "stdin and file" "cmp input - | sed s/byte/char/" \
+testcmd "stdin and file" "input - | sed s/byte/char/" \
"input - differ: char 4, line 2\n" "ab\nc\n" "ab\nx\n"
-#testing "stdin and stdin" "cmp input -" "" "" "ab\nc\n"
+testcmd "-n skip1 skip2" "-n 3 input - 3 5 && echo yes" "yes\n" "abcdef123" "vwxyzdef987"
diff --git a/tests/fmt.test b/tests/fmt.test
index 201952ef..7be2e4e7 100755
--- a/tests/fmt.test
+++ b/tests/fmt.test
@@ -26,7 +26,8 @@ testing "" "fmt -w 11" "1 2 3 4 5\n6 7 8 9 0\n" "" "1 2 3 4 5 6 7 8 9 0\n"
testing "" "fmt -w 12" "1 2 3 4 5 6\n7 8 9 0\n" "" "1 2 3 4 5 6 7 8 9 0\n"
testing "matched tab indent" "fmt" "\thello world\n" "" "\thello\n\tworld"
-testing "matched tab/space" "fmt" ' hello world\n' "" \
+# Version skew: debian is now emitting \t instead of "first line's indent"
+toyonly testing "matched tab/space" "fmt" ' hello world\n' "" \
" hello\n\tworld"
testing "matched space/tab" "fmt" "\thello world\n" "" "\thello\n world"
diff --git a/tests/nl.test b/tests/nl.test
index 046773f5..4bf8e394 100755
--- a/tests/nl.test
+++ b/tests/nl.test
@@ -52,4 +52,5 @@ testing "-l" "nl -ba -l2 -w2 - input" \
testing "no space" "nl -w 1 -v 42" "42\tline\n" "" "line\n"
# Should test for -E but no other implementation seems to have it?
-#testing "-E" "nl -w2 -sx -Ebp'(one|two)'" " 1x" "one\nand\ntwo\n"
+toyonly testing "-E" "nl -w2 -sx -Ebp'(one|two)'" " 1xone\n and\n 2xtwo\n" \
+ "" "one\nand\ntwo\n"
diff --git a/tests/sort.test b/tests/sort.test
index dd2b8263..5fe925e1 100755
--- a/tests/sort.test
+++ b/tests/sort.test
@@ -88,7 +88,7 @@ testing "key edge case with -t" "sort -n -k4 -t/" \
/usr/lib/prebaseconfig.d/6
"
-testing "-x" "sort -x" "010\na0\n 0c0\n" "" "a0\n010\n 0c0\n"
+toyonly testing "-x" "sort -x" "010\na0\n 0c0\n" "" "a0\n010\n 0c0\n"
# Test that -f applies to key or fallback independently
@@ -97,10 +97,12 @@ testing "" "sort -k2,2" "a B C\na B a\nA b b\n" "" "a B a\nA b b\na B C\n"
testing "" "sort -f -k2,2" "A b b\na B C\na B a\n" "" "a B a\nA b b\na B C\n"
testing "" "sort -t, -k3n" "3,4,1,2\n4,1,2,3\n1,2,3,4\n2,3,4,1\n" "" \
"1,2,3,4\n2,3,4,1\n4,1,2,3\n3,4,1,2\n"
-testing "-kx" "sort -k1,1x" "3\na\n0c\n" "" "0c\na\n3\n"
+toyonly testing "-kx" "sort -k1,1x" "3\na\n0c\n" "" "0c\na\n3\n"
-testing "" "sort -V" "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"
+# This has irredeemable version skew on the host and no standard defining it.
+# testing "-V" "LANG=c sort -V" \
+# "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"
optional SORT_FLOAT
@@ -108,3 +110,10 @@ optional SORT_FLOAT
testing "-g" "sort -g" \
"bork\nNaN\n-inf\n0.4\n1.222\n01.37\n2.1\n+infinity\n" "" \
"01.37\n1.222\n2.1\n0.4\nNaN\nbork\n-inf\n+infinity\n"
+
+# -n without number sorts as leading zero, but fallback is whole string
+testcmd '-n without number sorts as leading zero' '-n' \
+ '-1\n0A\n0D\nC\n1z\n3b\n' '' '1z\n0D\n3b\nC\n-1\n0A\n'
+
+testcmd '-u implies -s' '-uk2,2n' 'zero 1\nthree 2\nfour 3\n' '' \
+ 'zero 1\none 1\nfour 3\ntwo 1\nthree 2\nalso 1'
diff --git a/toys.h b/toys.h
index 40d8993d..60e22467 100644
--- a/toys.h
+++ b/toys.h
@@ -56,15 +56,16 @@
#include <sys/socket.h>
#include <sys/un.h>
-// Internationalization support (also in POSIX and LSB)
+// Internationalization support (also in POSIX)
#include <langinfo.h>
#include <locale.h>
#include <wchar.h>
#include <wctype.h>
-// LSB 4.1 headers
+// Non-posix headers
#include <sys/ioctl.h>
+#include <sys/syscall.h>
#include "lib/lib.h"
#include "lib/lsm.h"
diff --git a/toys/android/README b/toys/android/README
index d471a20a..b1b627ca 100644
--- a/toys/android/README
+++ b/toys/android/README
@@ -1,5 +1,6 @@
-Android
+Android commands
-Commands primarily used by Android, not vanilla Linux. (Also SELinux stuff.)
+Commands primarily used by Android, not present in vanilla Linux.
+(Mostly SELinux stuff.)
Bug Elliott Hughes <enh@google.com> about this.
diff --git a/toys/example/demo_scankey.c b/toys/example/demo_scankey.c
index cc625092..05ffc414 100644
--- a/toys/example/demo_scankey.c
+++ b/toys/example/demo_scankey.c
@@ -30,20 +30,17 @@ void demo_scankey_main(void)
y = 1;
sigatexit(tty_sigreset); // Make ctrl-c restore tty
- tty_esc("?25l"); // hide cursor
- tty_esc("0m"); // reset color to default
- tty_esc("2J"); // Clear screen
+ // hide cursor, reset color to default, clear screen
+ xputsn("\e[?25l\e0m\e[2J");
xset_terminal(1, 1, 0, 0); // Raw mode
for (;;) {
- tty_jump(x, y);
- xputc(c);
+ printf("\e[%u;%uH%c", y+1, x+1, c);
t[1&++tick] = time(0);
if (t[0] != t[1]) terminal_probesize(&width, &height);
// Don't block first time through, to force header print
key = scan_key_getsize(scratch, -1*!!t[0], &width, &height);
- tty_jump(0, 0);
- printf("ESC to exit: ");
+ printf("\e[HESC to exit: ");
// Print unknown escape sequence
if (*scratch) {
printf("key=[ESC");
@@ -52,14 +49,13 @@ void demo_scankey_main(void)
printf("%c", key);
printf("] ");
} else printf("key=%d ", key);
- printf("x=%d y=%d width=%d height=%d\033[K", x, y, width, height);
+ printf("x=%d y=%d width=%d height=%d\e[K", x, y, width, height);
fflush(0);
if (key == -2) continue;
if (key <= ' ') break;
if (key>=256) {
- tty_jump(x, y);
- xputc(' ');
+ printf("\e[%u;%uH ", y+1, x+1);
key -= 256;
if (key==KEY_UP) y--;
diff --git a/toys/lsb/dmesg.c b/toys/lsb/dmesg.c
index 8736a8e5..384d6fcd 100644
--- a/toys/lsb/dmesg.c
+++ b/toys/lsb/dmesg.c
@@ -42,7 +42,7 @@ GLOBALS(
static void color(int c)
{
- if (TT.use_color) printf("\033[%dm", c);
+ if (TT.use_color) printf("\e[%dm", c);
}
static void format_message(char *msg, int new)
diff --git a/toys/net/README b/toys/net/README
index 8708e4b5..49259ca0 100644
--- a/toys/net/README
+++ b/toys/net/README
@@ -1 +1,6 @@
-Networking
+Networking commands
+
+The Internet Engineering Task Force publishes standards drafts at
+https://www.ietf.org/rfc/rfc-index.txt (ala https://www.ietf.org/rfc/rfc3.txt)
+and the commands tend to be documented in manual page section 8
+https://man7.org/linux/man-pages/dir_section_8.html
diff --git a/toys/net/host.c b/toys/net/host.c
new file mode 100644
index 00000000..20331678
--- /dev/null
+++ b/toys/net/host.c
@@ -0,0 +1,196 @@
+/* host.c - DNS lookup utility
+ *
+ * Copyright 2014 Rich Felker <dalias@aerifal.cx>
+ *
+ * No standard, but there's a version in bind9
+ * See https://www.ietf.org/rfc/rfc1035.txt
+ * See https://www.ietf.org/rfc/rfc3596.txt
+
+USE_HOST(NEWTOY(host, "<1>2avt:", TOYFLAG_USR|TOYFLAG_BIN))
+
+config HOST
+ bool "host"
+ default y
+ help
+ usage: host [-v] [-t TYPE] NAME [SERVER]
+
+ Look up DNS records for NAME, either domain name or IPv4/IPv6 address to
+ reverse lookup, from SERVER or default DNS server(s).
+
+ -a All records
+ -t TYPE Record TYPE (number or ANY A AAAA CNAME MX NS PTR SOA SRV TXT)
+ -v Verbose
+*/
+
+#define FOR_host
+#include "toys.h"
+#include <resolv.h>
+
+GLOBALS(
+ char *t;
+
+ char **nsname;
+ unsigned nslen;
+)
+
+static const struct rrt {
+ char *name, *msg;
+ 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 }
+};
+
+int xdn_expand(char *packet, char *endpkt, char *comp, char *expand, int elen)
+{
+ int i = dn_expand(packet, endpkt, comp, expand, elen);
+
+ if (i<1) error_exit("bad dn_expand");
+
+ return i;
+}
+
+// Fetch "nameserve" lines from /etc/resolv.conf. Ignores 'options' lines
+static void get_nsname(char **pline, long len)
+{
+ char *line, *p;
+
+ if (!len) return;
+ line = *pline;
+ if (strstart(&line, "nameserver") && isspace(*line)) {
+ while (isspace(*line)) line++;
+ for (p = line; *p && !isspace(*p) && *p!='#'; p++);
+ if (p == line) return;
+ *p = 0;
+ if (!(TT.nslen&8))
+ TT.nsname = xrealloc(TT.nsname, (TT.nslen+8)*sizeof(void *));
+ TT.nsname[TT.nslen++] = xstrdup(line);
+ }
+}
+
+void host_main(void)
+{
+ int verbose = FLAG(a)||FLAG(v), type, abuf_len = 65536, //Largest TCP response
+ i, j, sec, rcode, qlen, alen QUIET, pllen = 0, t2len = 2048;
+ unsigned count, ttl;
+ char *abuf = xmalloc(abuf_len), *name = *toys.optargs, *p, *ss,
+ *t2 = toybuf+t2len;
+ struct addrinfo *ai;
+
+ // What kind of query are we doing?
+ if (!TT.t && FLAG(a)) TT.t = "255";
+ if (!getaddrinfo(name, 0,&(struct addrinfo){.ai_flags=AI_NUMERICHOST}, &ai)) {
+ name = toybuf;
+ if (ai->ai_family == AF_INET) {
+ p = (void *)&((struct sockaddr_in *)ai->ai_addr)->sin_addr;
+ sprintf(name, "%d.%d.%d.%d.in-addr.arpa", p[3], p[2], p[1], p[0]);
+ } else if (ai->ai_family == AF_INET6) {
+ p = (void *)&((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr;
+ for (j = 0, i = 15; i>=0; i--)
+ j += sprintf(name+j, "%x.%x.", p[i]&15, p[i]>>4);
+ strcpy(name+j, "ip6.arpa");
+ }
+ if (!TT.t) TT.t = "12";
+ } else if (!TT.t) TT.t = "1";
+
+ // 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 {
+ for (i = 0; i<ARRAY_LEN(rrt); i++) if (!strcasecmp(TT.t, rrt[i].name)) {
+ type = rrt[i].type;
+ break;
+ }
+ if (i == ARRAY_LEN(rrt)) error_exit("bad -t: %s", TT.t);
+ }
+ qlen = res_mkquery(0, name, 1, type, 0, 0, 0, t2, 280); //t2len);
+ if (qlen<0) error_exit("bad NAME: %s", name);
+
+ // Grab nameservers
+ if (toys.optargs[1]) TT.nsname = toys.optargs+1;
+ else do_lines(xopen("/etc/resolv.conf", O_RDONLY), '\n', get_nsname);
+ if (!TT.nsname) error_exit("No nameservers");
+
+ // Send one query packet to each server until we receive response
+ while (*TT.nsname) {
+ if (verbose) printf("Using domain server %s:\n", *TT.nsname);
+ ai = xgetaddrinfo(*TT.nsname, "53", 0, SOCK_DGRAM, 0, 0);
+ i = xsocket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ xconnect(i, ai->ai_addr, ai->ai_addrlen);
+ setsockopt(i, SOL_SOCKET, SO_RCVTIMEO, &(struct timeval){ .tv_sec = 5 },
+ sizeof(struct timeval));
+ send(i, t2, qlen, 0);
+ if (16 < (alen = recv(i, abuf, abuf_len, 0))) break;
+ if (!*++TT.nsname) error_exit("Host not found.");
+ close(i);
+ }
+
+ // Did it error?
+ rcode = abuf[3]&7;
+ if (verbose) {
+ printf("rcode = %d, ancount = %d\n", rcode, (int)peek_be(abuf+6, 2));
+ if (!(abuf[2]&4)) puts("The following answer is not authoritative:");
+ }
+ if (rcode) error_exit("Host not found: %s",
+ (char *[]){ "Format error", "Server failure",
+ "Non-existant domain", "Not implemented", "Refused", ""}[rcode-1]);
+
+ // Print the result
+ p = abuf + 12;
+ for (sec = 0; sec<(2<<verbose); sec++) {
+ count = peek_be(abuf+4+2*sec, 2);
+ if (verbose && count>0 && sec>1)
+ puts(sec==2 ? "For authoritative answers, see:"
+ : "Additional information:");
+
+ for (; count--; p += pllen) {
+ p += xdn_expand(abuf, abuf+alen, p, toybuf, 4096-t2len);
+ if (alen-(p-abuf)<10) error_exit("tilt");
+ type = peek_be(p, 2);
+ p += 4;
+ if (!sec) continue;
+ ttl = peek_be(p, 4);
+ p += 4;
+ 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==6) {
+ ss = p+xdn_expand(abuf, abuf+alen, p, t2, t2len-1);
+ j = strlen(t2);
+ t2[j++] = ' ';
+ ss += xdn_expand(abuf, abuf+alen, ss, t2+j, t2len-j);
+ j += strlen(t2+j);
+ snprintf(t2+j, t2len-j, "(\n\t\t%u\t;serial (version)\n\t\t%u\t"
+ ";refresh period\n\t\t%u\t;retry interval\n\t\t%u\t;expire time\n"
+ "\t\t%u\t;default ttl\n\t\t)", (unsigned)peek_be(ss, 4),
+ (unsigned)peek_be(ss+4, 4), (unsigned)peek_be(ss+8, 4),
+ (unsigned)peek_be(ss+12, 4), (unsigned)peek_be(ss+16, 4));
+ } else if (type==15) {
+ j = peek_be(p, 2);
+ j = sprintf(t2, verbose ? "%d " : "(pri=%d) by ", j);
+ xdn_expand(abuf, abuf+alen, p+2, t2+j, t2len-j);
+ } else if (type==33) {
+ j = sprintf(t2, "%u %u %u ", (int)peek_be(p, 2), (int)peek_be(p+2, 2),
+ (int)peek_be(p+4, 2));
+ xdn_expand(abuf, abuf+alen, p+6, t2+j, t2len-j);
+ } else {
+ 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);
+ }
+ }
+
+ if (CFG_TOYBOX_FREE) free(abuf);
+ toys.exitval = rcode;
+}
diff --git a/toys/net/ping.c b/toys/net/ping.c
index 88b1b238..e7b296db 100644
--- a/toys/net/ping.c
+++ b/toys/net/ping.c
@@ -301,9 +301,7 @@ void ping_main(void)
toys.exitval = 0;
}
- sigatexit(0);
- summary(0);
-
+ // summary(0) gets called for us atexit.
if (CFG_TOYBOX_FREE) {
freeaddrinfo(ai2);
if (ifa2) freeifaddrs(ifa2);
diff --git a/toys/other/chrt.c b/toys/other/chrt.c
index 6732a711..1a8222fa 100644
--- a/toys/other/chrt.c
+++ b/toys/other/chrt.c
@@ -35,7 +35,6 @@ GLOBALS(
// musl-libc intentionally broke sched_get_priority_min() and friends in
// commit 1e21e78bf7a5 because its maintainer didn't like those Linux
// system calls, so work around it here.
-#include <sys/syscall.h>
#define sched_get_priority_min(policy) \
(int)syscall(SYS_sched_get_priority_min, (int)policy)
#define sched_get_priority_max(policy) \
@@ -48,7 +47,7 @@ GLOBALS(
syscall(SYS_sched_setscheduler, (pid_t)pid, (int)scheduler, (void *)param)
#endif
-char *polnames[] = {
+static char *polnames[] = {
"SCHED_OTHER", "SCHED_FIFO", "SCHED_RR", "SCHED_BATCH", 0, "SCHED_IDLE",
"SCHED_DEADLINE"
};
diff --git a/toys/other/clear.c b/toys/other/clear.c
index 842579f8..400fe7b3 100644
--- a/toys/other/clear.c
+++ b/toys/other/clear.c
@@ -15,5 +15,5 @@ config CLEAR
void clear_main(void)
{
- printf("\033[2J\033[H");
+ printf("\e[2J\e[H");
}
diff --git a/toys/other/hexedit.c b/toys/other/hexedit.c
index 5bfc598c..bf1c7a6a 100644
--- a/toys/other/hexedit.c
+++ b/toys/other/hexedit.c
@@ -2,7 +2,12 @@
*
* Copyright 2015 Rob Landley <rob@landley.net>
*
- * No standard
+ * No standard.
+ *
+ * See https://man7.org/linux/man-pages/man4/console_codes.4.html
+ * \e[#m - color change \e[y,xH - jump to x/y pos (1-based)
+ * \e[K - delete to EOL \e[25l - disable cursor (h to enable)
+ * \e[1L - zap line after cursor \e[1M - zap line before cursor
USE_HEXEDIT(NEWTOY(hexedit, "<1>1r", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
@@ -42,8 +47,7 @@ GLOBALS(
static void show_error(char *what)
{
- tty_jump(0, TT.rows);
- printf("\e[41m\e[37m\e[K\e[1m%s\e[0m", what);
+ printf("\e[%dH\e[41m\e[37m\e[K\e[1m%s\e[0m", TT.rows+1, what);
xflush(1);
msleep(500);
}
@@ -55,10 +59,7 @@ static int prompt(char *prompt, char *initial_value)
strcpy(TT.input, initial_value);
while (1) {
- tty_jump(0, TT.rows);
- tty_esc("K");
- printf("\e[1m%s: \e[0m%s", prompt, TT.input);
- tty_esc("?25h");
+ printf("\e[%dH\e[K\e[1m%s: \e[0m%s\e[?25h", TT.rows+1, prompt, TT.input);
xflush(1);
key = scan_key(TT.keybuf, -1);
@@ -73,8 +74,8 @@ static int prompt(char *prompt, char *initial_value)
else if (key >= ' ' && key < 0x7f && len < sizeof(TT.input))
TT.input[len++] = key;
}
+ printf("\e[?25l");
- tty_esc("?25l");
return yes;
}
@@ -88,28 +89,27 @@ static void draw_char(int ch)
if (TT.mode) {
if (ch>127) {
- tty_esc("2m");
+ printf("\e[2m");
ch &= 127;
}
if (ch<32 || ch==127) {
- tty_esc("7m");
+ printf("\e[7m");
if (ch==127) ch = 32;
else ch += 64;
}
xputc(ch);
} else {
if (ch < ' ') printf("\e[31m%c", ch + '@');
- else tty_esc("35m?");
+ else printf("\e[35m?");
}
- tty_esc("0m");
+ printf("\e[0m");
}
static void draw_status(void)
{
char line[80];
- tty_jump(0, TT.rows);
- tty_esc("K");
+ printf("\e[%dH\e[K", TT.rows+1);
snprintf(line, sizeof(line), "\"%s\"%s, %#llx/%#llx", *toys.optargs,
FLAG(r) ? " [readonly]" : "", TT.pos, TT.len);
@@ -139,16 +139,15 @@ static void draw_line(long long yy)
for (x=0; x<xx; x++) draw_char(TT.data[yy+x]);
printf("%*s", 16-xx, "");
}
- tty_esc("K");
+ printf("\e[K");
}
static void draw_page(void)
{
int y;
- tty_jump(0, 0);
for (y = 0; y<TT.rows; y++) {
- if (y) printf("\r\n");
+ printf(y ? "\r\n" : "\e[H");
draw_line(y);
}
draw_status();
@@ -161,18 +160,15 @@ static void highlight(int xx, int yy, int side)
int i;
// Display cursor in hex area.
- tty_jump(2+TT.numlen+3*xx, yy);
- tty_esc("0m");
- if (side!=2) tty_esc("7m");
+ printf("\e[%u;%uH\e[%dm", yy+1, TT.numlen+3*(xx+1), 7*(side!=2));
if (side>1) draw_byte(cc);
else for (i=0; i<2;) {
- if (side==i) tty_esc("32m");
+ if (side==i) printf("\e[32m");
printf("%x", (cc>>(4*(1&++i)))&15);
}
- tty_jump(TT.numlen+17*3+xx, yy);
// Display cursor in text area.
- if (side!=2) tty_esc("7m");
+ printf("\e[7m\e[%u;%uH"+4*(side==2), yy+1, 1+TT.numlen+17*3+xx);
draw_char(cc);
}
@@ -210,9 +206,7 @@ void hexedit_main(void)
if (TT.rows) TT.rows--;
xsignal(SIGWINCH, generic_signal);
sigatexit(tty_sigreset);
- tty_esc("0m");
- tty_esc("?25l");
- xflush(1);
+ dprintf(1, "\e[0m\e[?25l");
xset_terminal(1, 1, 0, 0);
if (access(*toys.optargs, W_OK)) toys.optflags |= FLAG_r;
@@ -234,29 +228,30 @@ void hexedit_main(void)
x = TT.pos&15;
y = TT.pos/16;
+ // scroll up
while (y<TT.base) {
if (TT.base-y>(TT.rows/2)) {
TT.base = y;
draw_page();
} else {
TT.base--;
- tty_jump(0, 0);
- tty_esc("1L");
+ printf("\e[H\e[1L");
draw_line(0);
}
}
+
+ // scroll down
while (y>=TT.base+TT.rows) {
if (y-(TT.base+TT.rows)>(TT.rows/2)) {
TT.base = y-TT.rows-1;
draw_page();
} else {
TT.base++;
- tty_jump(0, 0);
- tty_esc("1M");
- tty_jump(0, TT.rows-1);
+ printf("\e[H\e[1M\e[%uH", TT.rows);
draw_line(TT.rows-1);
}
}
+
draw_status();
y -= TT.base;
@@ -278,7 +273,7 @@ void hexedit_main(void)
if (key == 'x') {
TT.mode = !TT.mode;
- tty_esc("0m");
+ printf("\e[0m");
draw_page();
continue;
}
diff --git a/toys/other/insmod.c b/toys/other/insmod.c
index a052f5a0..176e5a6d 100644
--- a/toys/other/insmod.c
+++ b/toys/other/insmod.c
@@ -15,8 +15,6 @@ config INSMOD
#include "toys.h"
-#include <sys/syscall.h>
-
void insmod_main(void)
{
int fd = xopenro(*toys.optargs);
diff --git a/toys/other/ionice.c b/toys/other/ionice.c
index f356c5fe..d313930e 100644
--- a/toys/other/ionice.c
+++ b/toys/other/ionice.c
@@ -37,7 +37,6 @@ config IORENICE
#define FOR_ionice
#include "toys.h"
-#include <sys/syscall.h>
GLOBALS(
long p, n, c;
diff --git a/toys/other/lsusb.c b/toys/other/lsusb.c
index 031dbd93..6df21aec 100644
--- a/toys/other/lsusb.c
+++ b/toys/other/lsusb.c
@@ -13,30 +13,52 @@ config LSUSB
List USB hosts/devices.
*/
+#define FOR_lsusb
#include "toys.h"
+GLOBALS(
+ void *ids;
+)
+
+struct ids {
+ struct ids *next, *child;
+ int id;
+ char name[];
+};
+
static int list_device(struct dirtree *new)
{
FILE *file;
char *name;
- int busnum = 0, devnum = 0, pid = 0, vid = 0;
+ struct ids *ids;
+ int busnum = 0, devnum = 0, pid = 0, vid = 0, count = 0;
if (!new->parent) return DIRTREE_RECURSE;
if (new->name[0] == '.') return 0;
- name = dirtree_path(new, 0);
- sprintf(toybuf, "%s/uevent", name);
- file = fopen(toybuf, "r");
- if (file) {
- int count = 0;
-
- while (fgets(toybuf, sizeof(toybuf), file))
- if (sscanf(toybuf, "BUSNUM=%u\n", &busnum)
- || sscanf(toybuf, "DEVNUM=%u\n", &devnum)
- || sscanf(toybuf, "PRODUCT=%x/%x/", &pid, &vid)) count++;
-
- if (count == 3)
- printf("Bus %03d Device %03d: ID %04x:%04x\n", busnum, devnum, pid, vid);
- fclose(file);
+
+ // Read data from proc file
+ sprintf(toybuf, "%s/uevent", name = dirtree_path(new, 0));
+ if (!(file = fopen(toybuf, "r"))) return 0;
+ while (fgets(toybuf, sizeof(toybuf), file))
+ if (sscanf(toybuf, "BUSNUM=%u\n", &busnum)
+ || sscanf(toybuf, "DEVNUM=%u\n", &devnum)
+ || sscanf(toybuf, "PRODUCT=%x/%x/", &pid, &vid)) count++;
+ fclose(file);
+
+ // Output with any matching ids data
+ if (count == 3) {
+ printf("Bus %03d Device %03d: ID %04x:%04x", busnum, devnum, pid, vid);
+ for (ids = TT.ids; ids; ids = ids->next) {
+ if (pid != ids->id) continue;
+ printf("%s", ids->name);
+ for (ids = ids->child; ids; ids = ids->next) {
+ if (vid != ids->id) continue;
+ printf("%s", ids->name);
+ break;
+ }
+ break;
+ }
+ xputc('\n');
}
free(name);
@@ -45,5 +67,33 @@ static int list_device(struct dirtree *new)
void lsusb_main(void)
{
+ int fd;
+
+ // Parse http://www.linux-usb.org/usb.ids file (if available)
+ if (-1 != (fd = open("/etc/usb.ids", O_RDONLY))) {
+ FILE *fp = fdopen(fd, "r");
+ char *s, *ss;
+ struct ids *ids, *tids;
+
+ while ((s = xgetline(fp))) {
+ fd = estrtol(s, &ss, 16);
+ if (ss == s+4+(*s=='\t') && *ss++==' ') {
+ ids = xmalloc(sizeof(*ids)+strlen(ss)+1);
+ ids->child = 0;
+ ids->id = fd;
+ strcpy(ids->name, ss);
+ if (!TT.ids || *s!='\t') {
+ ids->next = TT.ids;
+ TT.ids = ids;
+ } else {
+ tids = TT.ids;
+ ids->next = tids->child;
+ tids->child = ids;
+ }
+ }
+ free(s);
+ }
+ fclose(fp);
+ }
dirtree_read("/sys/bus/usb/devices/", list_device);
}
diff --git a/toys/other/nsenter.c b/toys/other/nsenter.c
index 65469356..78b7598f 100644
--- a/toys/other/nsenter.c
+++ b/toys/other/nsenter.c
@@ -64,7 +64,6 @@ config NSENTER
#define FOR_nsenter
#include "toys.h"
-#include <sys/syscall.h>
#include <linux/sched.h>
#define unshare(flags) syscall(SYS_unshare, flags)
diff --git a/toys/other/pivot_root.c b/toys/other/pivot_root.c
index 7748032b..f9a89189 100644
--- a/toys/other/pivot_root.c
+++ b/toys/other/pivot_root.c
@@ -22,9 +22,6 @@ config PIVOT_ROOT
#define FOR_pivot_root
#include "toys.h"
-#include <sys/syscall.h>
-#include <unistd.h>
-
void pivot_root_main(void)
{
if (syscall(__NR_pivot_root, toys.optargs[0], toys.optargs[1]))
diff --git a/toys/other/pwgen.c b/toys/other/pwgen.c
index c6621ccd..c34daf5a 100644
--- a/toys/other/pwgen.c
+++ b/toys/other/pwgen.c
@@ -61,7 +61,7 @@ void pwgen_main(void)
else c |= (0x80&randbuf[rand])>>2;
}
if (FLAG(0) && c>='0' && c<='9') continue;
- if (FLAG(B) && strchr("0O1lI'`.,", c)) continue;
+ if (FLAG(B) && strchr("0O1lI8B5S2ZD'`.,", c)) continue;
if (FLAG(v) && strchr("aeiou", tolower(c))) continue;
if (!FLAG(y) || (0x80&randbuf[rand]))
if (c<'0' || (c>'9' && c<'A') || (c>'Z' && c<'a') || c>'z') continue;
diff --git a/toys/other/readahead.c b/toys/other/readahead.c
index 4edd6516..3221227a 100644
--- a/toys/other/readahead.c
+++ b/toys/other/readahead.c
@@ -17,8 +17,6 @@ config READAHEAD
#include "toys.h"
-#include <sys/syscall.h>
-
static void do_readahead(int fd, char *name)
{
int rc;
diff --git a/toys/other/reset.c b/toys/other/reset.c
index 4d16a4a3..8723760d 100644
--- a/toys/other/reset.c
+++ b/toys/other/reset.c
@@ -3,6 +3,9 @@
* Copyright 2015 Rob Landley <rob@landley.net>
*
* No standard.
+ *
+ * In 1979 3BSD's tset had a sleep(1) to let mechanical printer-and-ink
+ * terminals "settle down". We're not doing that.
USE_RESET(NEWTOY(reset, 0, TOYFLAG_USR|TOYFLAG_BIN))
@@ -22,5 +25,5 @@ void reset_main(void)
// man 4 console_codes: reset terminal is ESC (no left bracket) c
// DEC private mode set enable wraparound sequence.
- xwrite(fd<0 ? 1 : fd, "\033c\033[?7h", 2);
+ xwrite(fd<0 ? 1 : fd, "\ec\e[?7h", 2);
}
diff --git a/toys/other/rmmod.c b/toys/other/rmmod.c
index b1fd2057..0450c0bc 100644
--- a/toys/other/rmmod.c
+++ b/toys/other/rmmod.c
@@ -19,7 +19,6 @@ config RMMOD
#define FOR_rmmod
#include "toys.h"
-#include <sys/syscall.h>
#define delete_module(mod, flags) syscall(__NR_delete_module, mod, flags)
void rmmod_main(void)
diff --git a/toys/other/taskset.c b/toys/other/taskset.c
index 6a9de77f..2a9ae029 100644
--- a/toys/other/taskset.c
+++ b/toys/other/taskset.c
@@ -34,7 +34,6 @@ config TASKSET
#define FOR_taskset
#include "toys.h"
-#include <sys/syscall.h>
#define sched_setaffinity(pid, size, cpuset) \
syscall(__NR_sched_setaffinity, (pid_t)pid, (size_t)size, (void *)cpuset)
#define sched_getaffinity(pid, size, cpuset) \
diff --git a/toys/other/uclampset.c b/toys/other/uclampset.c
index bc3688ee..acf50bda 100644
--- a/toys/other/uclampset.c
+++ b/toys/other/uclampset.c
@@ -30,7 +30,6 @@ GLOBALS(
)
// Added to 5.3 kernel (commit a509a7cd7974): too new to rely on headers
-#include <sys/syscall.h>
#ifndef SCHED_FLAG_RESET_ON_FORK
#define SCHED_FLAG_RESET_ON_FORK 0x01
#define SCHED_FLAG_KEEP_POLICY 0x08
diff --git a/toys/pending/README b/toys/pending/README
index 2eb83e11..de44b024 100644
--- a/toys/pending/README
+++ b/toys/pending/README
@@ -1,4 +1,4 @@
-pending (see toys/pending/README)
+Pending (unfinished) commands
Commands in this directory are external submissions awaiting review and/or
cleanup before being "promoted" to one of the other directories.
diff --git a/toys/pending/diff.c b/toys/pending/diff.c
index e93c622c..4dd01653 100644
--- a/toys/pending/diff.c
+++ b/toys/pending/diff.c
@@ -427,8 +427,8 @@ static void print_diff(int a, int b, char c, int *off_set, FILE *fp)
char *reset = NULL;
if (c != ' ' && (toys.optflags & FLAG_color)) {
- printf("\033[%dm", c == '+' ? 32 : 31);
- reset = "\033[0m";
+ printf("\e[%dm", c == '+' ? 32 : 31);
+ reset = "\e[0m";
}
for (i = a; i <= b; i++) {
@@ -639,7 +639,7 @@ static void do_diff(char **files)
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("\033[1m");
+ 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))
@@ -648,7 +648,7 @@ static void do_diff(char **files)
while (llist->next) llist = llist->next;
printf("+++ %s\n", llist->arg);
}
- if (toys.optflags & FLAG_color) printf("\033[0m");
+ if (toys.optflags & FLAG_color) printf("\e[0m");
struct diff *t, *ptr1 = d, *ptr2 = d;
while (i) {
@@ -683,7 +683,7 @@ calc_ct:
start2 = MAX(1, ptr1->c - (ptr1->a - ptr1->suff));
end2 = ptr2->prev - ptr2->b + ptr2->d;
- if (toys.optflags & FLAG_color) printf("\033[36m");
+ 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(' ');
@@ -692,7 +692,7 @@ calc_ct:
if ((end2 - start2 +1) != 1) printf(",%ld ", (end2 - start2 +1));
else putchar(' ');
printf("@@");
- if (toys.optflags & FLAG_color) printf("\033[0m");
+ if (toys.optflags & FLAG_color) printf("\e[0m");
putchar('\n');
for (t = ptr1; t <= ptr2; t++) {
diff --git a/toys/pending/host.c b/toys/pending/host.c
deleted file mode 100644
index 1610301e..00000000
--- a/toys/pending/host.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/* host.c - DNS lookup utility
- *
- * Copyright 2014 Rich Felker <dalias@aerifal.cx>
- *
- * No standard, but there's a version in bind9
-
-USE_HOST(NEWTOY(host, "<1>2avt:", TOYFLAG_USR|TOYFLAG_BIN))
-
-config HOST
- bool "host"
- default n
- help
- usage: host [-av] [-t TYPE] NAME [SERVER]
-
- Perform DNS lookup on NAME, which can be a domain name to lookup,
- or an IPv4 dotted or IPv6 colon-separated address to reverse lookup.
- SERVER (if present) is the DNS server to use.
-
- -a -v -t ANY
- -t TYPE query records of type TYPE
- -v verbose
-*/
-
-#define FOR_host
-#include "toys.h"
-
-GLOBALS(
- char *type_str;
-)
-
-#include <resolv.h>
-
-#define PL_IP 1
-#define PL_NAME 2
-#define PL_DATA 3
-#define PL_TEXT 4
-#define PL_SOA 5
-#define PL_MX 6
-#define PL_SRV 7
-
-static const struct rrt {
- const char *name;
- const char *msg;
- int pl;
- int af;
-} rrt[] = {
- [1] = { "A", "has address", PL_IP, AF_INET },
- [28] = { "AAAA", "has address", PL_IP, AF_INET6 },
- [2] = { "NS", "name server", PL_NAME },
- [5] = { "CNAME", "is a nickname for", PL_NAME },
- [16] = { "TXT", "descriptive text", PL_TEXT },
- [6] = { "SOA", "start of authority", PL_SOA },
- [12] = { "PTR", "domain name pointer", PL_NAME },
- [15] = { "MX", "mail is handled", PL_MX },
- [33] = { "SRV", "mail is handled", PL_SRV },
- [255] = { "*", 0, 0 },
-};
-
-static const char rct[16][32] = {
- "Success",
- "Format error",
- "Server failure",
- "Non-existant domain",
- "Not implemented",
- "Refused",
-};
-
-void host_main(void)
-{
- int verbose=(toys.optflags & (FLAG_a|FLAG_v)), type,
- i, j, ret, sec, count, rcode, qlen, alen, pllen = 0,
- abuf_len = 65536; // Largest TCP response.
- unsigned ttl, pri, v[5];
- unsigned char *abuf = xmalloc(abuf_len);
- char *rrname = xmalloc(MAXDNAME);
- unsigned char qbuf[280], *p;
- char *name, *nsname, plname[640], ptrbuf[128];
- struct addrinfo *ai, iplit_hints = { .ai_flags = AI_NUMERICHOST };
-
- name = *toys.optargs;
- nsname = toys.optargs[1];
-
- if (!TT.type_str && (toys.optflags & FLAG_a)) TT.type_str = "255";
- if (!getaddrinfo(name, 0, &iplit_hints, &ai)) {
- unsigned char *a;
- static const char xdigits[] = "0123456789abcdef";
-
- if (ai->ai_family == AF_INET) {
- a = (void *)&((struct sockaddr_in *)ai->ai_addr)->sin_addr;
- snprintf(ptrbuf, sizeof(ptrbuf), "%d.%d.%d.%d.in-addr.arpa",
- a[3], a[2], a[1], a[0]);
- } else if (ai->ai_family == AF_INET6) {
- a = (void *)&((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr;
- for (j=0, i=15; i>=0; i--) {
- ptrbuf[j++] = xdigits[a[i]&15];
- ptrbuf[j++] = '.';
- ptrbuf[j++] = xdigits[a[i]>>4];
- ptrbuf[j++] = '.';
- }
- strcpy(ptrbuf+j, "ip6.arpa");
- }
- name = ptrbuf;
- if (!TT.type_str) TT.type_str="12";
- } else if (!TT.type_str) TT.type_str="1";
-
- if (TT.type_str[0]-'0' < 10u) type = atoi(TT.type_str);
- else {
- type = -1;
- for (i=0; i<ARRAY_LEN(rrt); i++) {
- if (rrt[i].name && !strcasecmp(TT.type_str, rrt[i].name)) {
- type = i;
- break;
- }
- }
- if (!strcasecmp(TT.type_str, "any")) type = 255;
- if (type < 0) error_exit("Invalid query type: %s", TT.type_str);
- }
-
- qlen = res_mkquery(0, name, 1, type, 0, 0, 0, qbuf, sizeof(qbuf));
- if (qlen < 0) error_exit("Invalid query parameters: %s", name);
-
- if (nsname) {
- struct addrinfo ns_hints = { .ai_socktype = SOCK_DGRAM };
-
- if ((ret = getaddrinfo(nsname, "53", &ns_hints, &ai)) < 0)
- error_exit("Error looking up server name: %s", gai_strerror(ret));
- int s = xsocket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
- xconnect(s, ai->ai_addr, ai->ai_addrlen);
- setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &(struct timeval){ .tv_sec = 5 },
- sizeof(struct timeval));
- printf("Using domain server %s:\n", nsname);
- send(s, qbuf, qlen, 0);
- alen = recv(s, abuf, abuf_len, 0);
- } else alen = res_send(qbuf, qlen, abuf, abuf_len);
-
- if (alen < 12) error_exit("Host not found.");
-
- rcode = abuf[3] & 15;
-
- if (verbose) {
- printf("rcode = %d (%s), ancount = %d\n",
- rcode, rct[rcode], 256*abuf[6] + abuf[7]);
- if (!(abuf[2] & 4)) printf("The following answer is not authoritative:\n");
- }
-
- if (rcode) error_exit("Host not found.");
-
- p = abuf + 12;
- for (sec=0; sec<4; sec++) {
- count = 256*abuf[4+2*sec] + abuf[5+2*sec];
- if (verbose && count>0 && sec>1)
- puts(sec==2 ? "For authoritative answers, see:"
- : "Additional information:");
-
- for (; count--; p += pllen) {
- p += dn_expand(abuf, abuf+alen, p, rrname, MAXDNAME);
- type = (p[0]<<8) + p[1];
- p += 4;
- if (!sec) continue;
- ttl = (p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3];
- p += 4;
- pllen = (p[0]<<8) + p[1];
- p += 2;
-
- switch (type<ARRAY_LEN(rrt) ? rrt[type].pl : 0) {
- case PL_IP:
- inet_ntop(rrt[type].af, p, plname, sizeof(plname));
- break;
- case PL_NAME:
- dn_expand(abuf, abuf+alen, p, plname, sizeof(plname));
- break;
- case PL_TEXT:
- snprintf(plname, sizeof(plname), "\"%.*s\"", pllen, p);
- break;
- case PL_SOA:
- i = dn_expand(abuf, abuf+alen, p, plname, sizeof(plname) - 1);
- strcat(plname, " ");
- i += dn_expand(abuf, abuf+alen, p+i, plname+strlen(plname),
- sizeof(plname)-strlen(plname));
- for (j=0; j<5; j++)
- v[j] = (p[i+4*j]<<24)+(p[1+i+4*j]<<16)+(p[2+i+4*j]<<8)+p[3+i+4*j];
- snprintf(plname+strlen(plname), sizeof(plname)-strlen(plname),
- "(\n\t\t%u\t;serial (version)\n"
- "\t\t%u\t;refresh period\n"
- "\t\t%u\t;retry interval\n"
- "\t\t%u\t;expire time\n"
- "\t\t%u\t;default ttl\n"
- "\t\t)", v[0], v[1], v[2], v[3], v[4]);
- break;
- case PL_MX:
- pri = (p[0]<<8)+p[1];
- snprintf(plname, sizeof(plname), verbose ? "%d " : "(pri=%d) by ", pri);
- dn_expand(abuf, abuf+alen, p+2, plname+strlen(plname),
- sizeof(plname) - strlen(plname));
- break;
- case PL_SRV:
- for (j=0; j<3; j++) v[j] = (p[2*j]<<8) + p[1+2*j];
- snprintf(plname, sizeof(plname), "%u %u %u ", v[0], v[1], v[2]);
- dn_expand(abuf, abuf+alen, p+6, plname+strlen(plname),
- sizeof(plname) - strlen(plname));
- break;
- default:
- printf("%s unsupported RR type %u\n", rrname, type);
- continue;
- }
-
- if (verbose)
- printf("%s\t%u\tIN %s\t%s\n", rrname, ttl, rrt[type].name, plname);
- else if (rrt[type].msg)
- printf("%s %s %s\n", rrname, rrt[type].msg, plname);
- }
- if (!verbose && sec==1) break;
- }
-
- if (CFG_TOYBOX_FREE) {
- free(abuf);
- free(rrname);
- }
- toys.exitval = rcode;
-}
diff --git a/toys/pending/init.c b/toys/pending/init.c
index 97ce23b0..05afb718 100644
--- a/toys/pending/init.c
+++ b/toys/pending/init.c
@@ -326,7 +326,7 @@ static void set_default(void)
{
sigset_t signal_set_c;
- xsignal_all_killers(0);
+ xsignal_all_killers(SIG_DFL);
sigfillset(&signal_set_c);
sigprocmask(SIG_UNBLOCK,&signal_set_c, NULL);
diff --git a/toys/pending/modprobe.c b/toys/pending/modprobe.c
index fcd1cc3e..45f8ea21 100644
--- a/toys/pending/modprobe.c
+++ b/toys/pending/modprobe.c
@@ -27,7 +27,6 @@ config MODPROBE
*/
#define FOR_modprobe
#include "toys.h"
-#include <sys/syscall.h>
GLOBALS(
struct arg_list *dirs;
diff --git a/toys/pending/strace.c b/toys/pending/strace.c
index a44dbdfa..ae8fca9f 100644
--- a/toys/pending/strace.c
+++ b/toys/pending/strace.c
@@ -19,7 +19,6 @@ config STRACE
*/
#include <sys/ptrace.h>
-#include <sys/syscall.h>
#include <sys/user.h>
#define FOR_strace
diff --git a/toys/pending/vi.c b/toys/pending/vi.c
index fc46f355..bbb0a90b 100644
--- a/toys/pending/vi.c
+++ b/toys/pending/vi.c
@@ -1294,9 +1294,9 @@ static int vi_crunch(FILE *out, int cols, int wc)
{
int ret = 0;
if (wc < 32 && TT.list) {
- tty_esc("1m");
+ xputsn("\e[1m");
ret = crunch_escape(out,cols,wc);
- tty_esc("m");
+ xputsn("\e[m");
} else if (wc == 0x09) {
if (out) {
int i = TT.tabstop;
@@ -1368,10 +1368,10 @@ static void draw_page()
if (TT.drawn_row<0 || TT.cur_row<0 || TT.scr_row<0) redraw = 3;
else if (abs(scroll)>TT.screen_height/2) redraw = 3;
- tty_jump(0, 0);
- if (redraw&2) tty_esc("2J"), tty_esc("H"); //clear screen
- else if (scroll>0) printf("\033[%dL", scroll); //scroll up
- else if (scroll<0) printf("\033[%dM", -scroll); //scroll down
+ xputsn("\e[H"); // jump to top left
+ if (redraw&2) xputsn("\e[2J\e[H"); //clear screen
+ else if (scroll>0) printf("\e[%dL", scroll); //scroll up
+ else if (scroll<0) printf("\e[%dM", -scroll); //scroll down
SOL = text_sol(TT.cursor);
bytes = text_getline(toybuf, SOL, ARRAY_LEN(toybuf));
@@ -1388,8 +1388,7 @@ static void draw_page()
end = line;
- tty_jump(0, y);
- tty_esc("2K");
+ printf("\e[%u;0H\e[2K", y+1);
//find cursor position
aw = crunch_nstr(&end, INT_MAX, bytes, 0, "\t\n", vi_crunch);
@@ -1454,14 +1453,14 @@ static void draw_page()
scroll++, draw_line++;
else if (scroll>0) scroll--, draw_line++;
- tty_jump(0, y);
+ printf("\e[%u;0H", y+1);
if (draw_line) {
- tty_esc("2K");
+ printf("\e[2K");
if (line && strlen(line)) {
aw = crunch_nstr(&line, clip, bytes, 0, "\t\n", vi_crunch);
crunch_str(&line, TT.screen_width-1, stdout, "\t\n", vi_crunch);
if ( *line ) printf("@");
- } else printf("\033[2m~\033[m");
+ } else printf("\e[2m~\e[m");
}
if (SSOL+bytes < TT.filesize) {
line = toybuf;
@@ -1473,9 +1472,8 @@ static void draw_page()
TT.drawn_row = TT.scr_row, TT.drawn_col = clip;
// Finished updating visual area, show status line.
- tty_jump(0, TT.screen_height);
- tty_esc("2K");
- if (TT.vi_mode == 2) printf("\033[1m-- INSERT --\033[m");
+ printf("\e[%u;0H\e[2K", TT.screen_height+1);
+ if (TT.vi_mode == 2) printf("\e[1m-- INSERT --\e[m");
if (!TT.vi_mode) {
cx_scr = printf("%s", TT.il->data);
cy_scr = TT.screen_height;
@@ -1487,10 +1485,9 @@ static void draw_page()
(100*TT.cursor)/(TT.filesize ? : 1), TT.cur_row+1, TT.cur_col+1);
if (TT.cur_col != cx_scr) sprintf(toybuf+strlen(toybuf),"-%d", cx_scr+1);
}
- tty_jump(TT.screen_width-strlen(toybuf), TT.screen_height);
- printf("%s", toybuf);
-
- tty_jump(cx_scr, cy_scr);
+ printf("\e[%u;%uH%s\e[%u;%uH", TT.screen_height+1,
+ (int) (1+TT.screen_width-strlen(toybuf)),
+ toybuf, cy_scr+1, cx_scr+1);
xflush(1);
}
@@ -1525,7 +1522,7 @@ void vi_main(void)
set_terminal(0, 1, 0, 0);
//writes stdout into different xterm buffer so when we exit
//we dont get scroll log full of junk
- tty_esc("?1049h");
+ xputsn("\e[?1049h");
for (;;) {
int key = 0;
@@ -1696,5 +1693,5 @@ cleanup_vi:
linelist_unload();
free(TT.il->data), free(TT.il), free(TT.yank.data);
tty_reset();
- tty_esc("?1049l");
+ xputsn("\e[?1049l");
}
diff --git a/toys/posix/cmp.c b/toys/posix/cmp.c
index d1c73f1d..8e33c92d 100644
--- a/toys/posix/cmp.c
+++ b/toys/posix/cmp.c
@@ -4,17 +4,19 @@
*
* See http://opengroup.org/onlinepubs/9699919799/utilities/cmp.html
-USE_CMP(NEWTOY(cmp, "<1>2ls(silent)(quiet)[!ls]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
+USE_CMP(NEWTOY(cmp, "<1>4ls(silent)(quiet)n#<1[!ls]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)))
config CMP
bool "cmp"
default y
help
- usage: cmp [-l] [-s] FILE1 [FILE2 [SKIP1 [SKIP2]]]
+ usage: cmp [-ls] [-n LEN] FILE1 [FILE2 [SKIP1 [SKIP2]]]
- Compare the contents of two files. (Or stdin and file if only one given.)
+ Compare the contents of files (vs stdin if only one given), optionally
+ skipping bytes at start.
-l Show all differing bytes
+ -n LEN Compare at most LEN bytes
-s Silent
*/
@@ -22,16 +24,22 @@ config CMP
#include "toys.h"
GLOBALS(
+ long n;
+
int fd;
char *name;
)
+// We hijack loopfiles() to open and understand the "-" filename for us.
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;
char *buf2 = toybuf+size;
+ if (toys.optc>(i = 2+!!TT.fd) && lskip(fd, atolx(toys.optargs[i])))
+ error_exit("EOF on %s", name);
+
// First time through, cache the data and return.
if (!TT.fd) {
TT.name = name;
@@ -43,19 +51,17 @@ static void do_cmp(int fd, char *name)
toys.exitval = 0;
- for (;;) {
+ for (;!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 = len1 < len2 ? len1 : len2;
+ min_len = minof(len1, len2);
for (i=0; i<min_len; i++) {
if (toybuf[i] != buf2[i]) {
toys.exitval = 1;
- if (toys.optflags & FLAG_l)
- printf("%ld %o %o\n", byte_no, toybuf[i], buf2[i]);
+ if (FLAG(l)) printf("%ld %o %o\n", byte_no, toybuf[i], buf2[i]);
else {
- if (!(toys.optflags & FLAG_s))
- printf("%s %s differ: char %ld, line %ld\n",
+ if (!FLAG(s)) printf("%s %s differ: char %ld, line %ld\n",
TT.name, name, byte_no, line_no);
goto out;
}
@@ -64,21 +70,20 @@ static void do_cmp(int fd, char *name)
if (toybuf[i] == '\n') line_no++;
}
if (len1 != len2) {
- if (!(toys.optflags & FLAG_s))
- fprintf(stderr, "cmp: EOF on %s\n", len1 < len2 ? TT.name : name);
- toys.exitval = 1;
+ if (!FLAG(s)) error_msg("EOF on %s", len1 < len2 ? TT.name : name);
+ else toys.exitval = 1;
break;
}
if (len1 < 1) break;
}
out:
if (CFG_TOYBOX_FREE) close(TT.fd);
+ xexit();
}
void cmp_main(void)
{
toys.exitval = 2;
- loopfiles_rw(toys.optargs, O_CLOEXEC|(WARN_ONLY*!(toys.optflags&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/getconf.c b/toys/posix/getconf.c
index c5e05489..a8017b29 100644
--- a/toys/posix/getconf.c
+++ b/toys/posix/getconf.c
@@ -55,7 +55,7 @@ struct config {
// confstr(), or output the macro value directly.
// Probe the live system
-struct config sysconfs[] = {
+static struct config sysconfs[] = {
/* POSIX */
#define CONF(n) {"_POSIX_" #n,_SC_ ## n}
CONF(ADVISORY_INFO), CONF(BARRIERS), CONF(ASYNCHRONOUS_IO),
@@ -118,7 +118,7 @@ struct config sysconfs[] = {
};
// Probe the live system with a path
-struct config pathconfs[] = {
+static struct config pathconfs[] = {
#undef CONF
#define CONF(n) {#n,_PC_ ## n}
CONF(ASYNC_IO), CONF(CHOWN_RESTRICTED), CONF(FILESIZEBITS), CONF(LINK_MAX),
@@ -129,14 +129,14 @@ struct config pathconfs[] = {
};
// Strings out of a header
-struct config confstrs[] = {
+static struct config confstrs[] = {
#undef CONF
#define CONF(n) {#n,_CS_ ## n}
CONF(PATH), CONF(V7_ENV)
};
// Integers out of a header
-struct config limits[] = {
+static struct config limits[] = {
#undef CONF
#define CONF(n) {#n,n}
CONF(_POSIX_AIO_LISTIO_MAX), CONF(_POSIX_AIO_MAX), CONF(_POSIX_ARG_MAX),
@@ -167,7 +167,7 @@ struct config limits[] = {
};
// Names we need to handle ourselves (default to blank but shouldn't error)
-struct config others[] = {
+static struct config others[] = {
{"LFS_CFLAGS", 0}, {"LFS_LDFLAGS", 0}, {"LFS_LIBS", 0}
};
diff --git a/toys/posix/grep.c b/toys/posix/grep.c
index 6d23543d..0474f7db 100644
--- a/toys/posix/grep.c
+++ b/toys/posix/grep.c
@@ -461,11 +461,11 @@ void grep_main(void)
toys.optflags &= ~FLAG_color;
if (FLAG(color)) {
- TT.purple = "\033[35m";
- TT.cyan = "\033[36m";
- TT.red = "\033[1;31m";
- TT.green = "\033[32m";
- TT.grey = "\033[m";
+ TT.purple = "\e[35m";
+ TT.cyan = "\e[36m";
+ TT.red = "\e[1;31m";
+ TT.green = "\e[32m";
+ TT.grey = "\e[m";
} else TT.purple = TT.cyan = TT.red = TT.green = TT.grey = "";
if (FLAG(R)) toys.optflags |= FLAG_r;
diff --git a/toys/posix/ls.c b/toys/posix/ls.c
index d9cd90bd..15511059 100644
--- a/toys/posix/ls.c
+++ b/toys/posix/ls.c
@@ -84,7 +84,7 @@ static int crunch_qb(FILE *out, int cols, int wc)
for (i = 0; i<len; i++) {
*to++ = '\\';
if (strchr(TT.escmore, from[i])) *to++ = from[i];
- else if (-1 != (j = stridx("\\\a\b\033\f\n\r\t\v", from[i])))
+ else if (-1 != (j = stridx("\\\a\b\e\f\n\r\t\v", from[i])))
*to++ = "\\abefnrtv"[j];
else to += sprintf(to, "%03o", from[i]);
}
@@ -457,12 +457,12 @@ static void listfiles(int dirfd, struct dirtree *indir)
if (FLAG(color)) {
color = color_from_mode(st->st_mode);
- if (color) printf("\033[%d;%dm", color>>8, color&255);
+ if (color) printf("\e[%d;%dm", color>>8, color&255);
}
ss = dt->name;
crunch_str(&ss, INT_MAX, stdout, TT.escmore, crunch_qb);
- if (color) printf("\033[0m");
+ if (color) printf("\e[0m");
if ((FLAG(l)||FLAG(o)||FLAG(n)||FLAG(g)) && S_ISLNK(mode)) {
printf(" -> ");
@@ -472,11 +472,11 @@ static void listfiles(int dirfd, struct dirtree *indir)
if (fstatat(dirfd, dt->symlink, &st2, 0)) color = 256+31;
else color = color_from_mode(st2.st_mode);
- if (color) printf("\033[%d;%dm", color>>8, color&255);
+ if (color) printf("\e[%d;%dm", color>>8, color&255);
}
zprint(zap, "s", 0, (unsigned long)dt->symlink);
- if (!zap && color) printf("\033[0m");
+ if (!zap && color) printf("\e[0m");
}
if (et) xputc(et);
diff --git a/toys/posix/nl.c b/toys/posix/nl.c
index ef2d7ab3..af95d942 100644
--- a/toys/posix/nl.c
+++ b/toys/posix/nl.c
@@ -4,10 +4,10 @@
*
* See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/nl.html
*
- * This implements a subset: only one logical page (-ip), no sections (-dfh).
- * todo: -l
+ * Deviations from posix: only one logical page (no -ip), no sections (-dfh),
+ * add -E, support multiple FILE, -n output is long not int.
-USE_NL(NEWTOY(nl, "v#=1l#w#<0=6Eb:n:s:", TOYFLAG_USR|TOYFLAG_BIN))
+USE_NL(NEWTOY(nl, "v#=1l#w#<0=6b:n:s:E", TOYFLAG_USR|TOYFLAG_BIN))
config NL
bool "nl"
@@ -34,8 +34,7 @@ GLOBALS(
long w, l, v;
// Count of consecutive blank lines for -l has to persist between files
- long lcount;
- long slen;
+ long lcount, slen;
)
static void do_nl(char **pline, long len)
@@ -71,10 +70,10 @@ void nl_main(void)
sprintf(toybuf, "%%%s%s", clip, "*ld%s");
if (!TT.b) TT.b = "t";
- if (*TT.b == 'p' && TT.b[1])
- xregcomp((void *)(toybuf+16), TT.b+1,
- REG_NOSUB | (toys.optflags&FLAG_E)*REG_EXTENDED);
- else if (!strchr("atn", *TT.b)) error_exit("bad -b '%s'", TT.b);
+ if (*TT.b=='p' && TT.b[1])
+ xregcomp((void *)(toybuf+16), TT.b+1, REG_NOSUB|FLAG(E)*REG_EXTENDED);
+ else if (!TT.b[0] || TT.b[1] || !strchr("atn", *TT.b))
+ error_exit("bad -b '%s'", TT.b);
loopfiles_lines(toys.optargs, do_nl);
}
diff --git a/toys/posix/ps.c b/toys/posix/ps.c
index f8b2e03a..35bfbf45 100644
--- a/toys/posix/ps.c
+++ b/toys/posix/ps.c
@@ -43,6 +43,7 @@
* at right edge? (Not adjusting to screen size at all? Header wraps?)
* TODO: top: thread support and SMP
* TODO: pgrep -f only searches the amount of cmdline that fits in toybuf.
+ * TODO: pgrep qemu-system-i386 never matches because one char too long
USE_PS(NEWTOY(ps, "k(sort)*P(ppid)*aAdeflMno*O*p(pid)*s*t*Tu*U*g*G*wZ[!ol][+Ae][!oO]", TOYFLAG_BIN|TOYFLAG_LOCALE))
// stayroot because iotop needs root to read other process' proc/$$/io
@@ -1457,8 +1458,8 @@ static int header_line(int line, int rev)
if (FLAG(b)) puts(toybuf);
else {
- printf("%s%-*.*s%s\r\n", rev?"\033[7m":"", rev?TT.width:0, TT.width, toybuf,
- rev?"\033[0m":"");
+ printf("%s%-*.*s%s\r\n", rev?"\e[7m":"", rev?TT.width:0, TT.width, toybuf,
+ rev?"\e[0m":"");
}
return line-1;
@@ -1466,7 +1467,7 @@ static int header_line(int line, int rev)
static void top_cursor_cleanup(void)
{
- tty_esc("?25h");
+ xputsn("\e[?25h");
}
static void top_common(
@@ -1490,7 +1491,7 @@ static void top_common(
if (!FLAG(b)) {
setbuf(stdout, stdout_buf);
sigatexit(top_cursor_cleanup);
- tty_esc("?25l");
+ xputsn("\e[?25l");
}
toys.signal = SIGWINCH;
@@ -1565,7 +1566,7 @@ static void top_common(
if (recalc) {
qsort(mix.tb, mix.count, sizeof(struct procpid *), (void *)ksort);
if (!FLAG(b)) {
- printf("\033[H\033[J");
+ printf("\e[H\e[J");
if (toys.signal) {
toys.signal = 0;
terminal_probesize(&TT.width, &TT.height);
@@ -1672,7 +1673,7 @@ static void top_common(
lines = header_line(lines, 1);
}
if (!recalc && !FLAG(b))
- printf("\033[%dH\033[J", 1+TT.height-lines);
+ printf("\e[%dH\e[J", 1+TT.height-lines);
recalc = 1;
for (i = 0; i<lines && i+topoff<mix.count; i++) {
@@ -1680,9 +1681,9 @@ static void top_common(
int bold = !FLAG(b) && mix.tb[i+topoff]->state == 'R';
if (!FLAG(b) && i) putchar('\n');
- if (bold) printf("\033[1m");
+ if (bold) printf("\e[1m");
show_ps(mix.tb[i+topoff]);
- if (bold) printf("\033[m");
+ if (bold) printf("\e[m");
}
if (TT.top.n && !--TT.top.n) {
diff --git a/toys/posix/sort.c b/toys/posix/sort.c
index 9f38be82..c06b2a5f 100644
--- a/toys/posix/sort.c
+++ b/toys/posix/sort.c
@@ -61,7 +61,7 @@ GLOBALS(
char *o, *T, S;
void *key_list;
- int linecount;
+ unsigned linecount;
char **lines, *name;
)
@@ -72,8 +72,7 @@ GLOBALS(
#define FLAG_bb (1<<31) // Ignore trailing blanks
-struct sort_key
-{
+struct sort_key {
struct sort_key *next_key; // linked list
unsigned range[4]; // start word, start char, end word, end char
int flags;
@@ -115,7 +114,7 @@ static char *get_key_data(char *str, struct sort_key *key, int flags)
}
}
}
- if (!j) start=end;
+ if (!j) start = end;
}
// Key with explicit separator starts after the separator
@@ -194,7 +193,7 @@ static int compare_values(int flags, char *x, char *y)
}
if (yinf) return dy<0 ? 1 : -1;
- return dx>dy ? 1 : (dx<dy ? -1 : 0);
+ return dx<dy ? -1 : dx>dy;
} else if (flags & FLAG_M) {
struct tm thyme;
int dx;
@@ -227,14 +226,11 @@ static int compare_values(int flags, char *x, char *y)
}
}
return *x ? !!*y : -1;
+ // This is actually an integer sort with decimals sorted by string fallback.
} else if (flags & FLAG_n) {
- // Full floating point version of -n
- if (CFG_SORT_FLOAT) {
- double dx = atof(x), dy = atof(y);
+ long long dx = atoll(x), dy = atoll(y);
- return dx>dy ? 1 : (dx<dy ? -1 : 0);
- // Integer version of -n for tiny systems
- } else return atoi(x)-atoi(y);
+ return dx<dy ? -1 : dx>dy;
// Ascii sort
} else return ((flags&FLAG_f) ? strcasecmp : strcmp)(x, y);
@@ -247,8 +243,8 @@ static int compare_keys(const void *xarg, const void *yarg)
char *x, *y, *xx = *(char **)xarg, *yy = *(char **)yarg;
struct sort_key *key;
- for (key=(struct sort_key *)TT.key_list; !retval && key; key = key->next_key){
- flags = key->flags ? key->flags : toys.optflags;
+ for (key=(void *)TT.key_list; !retval && key; key = key->next_key) {
+ flags = key->flags ? : toys.optflags;
// Chop out and modify key chunks, handling -dfib
@@ -287,10 +283,8 @@ static void sort_lines(char **pline, long len)
// handle -c here so we don't allocate more memory than necessary.
if (FLAG(c)) {
- int j = FLAG(u) ? -1 : 0;
-
- if (TT.lines && compare_keys((void *)&TT.lines, &line)>j)
- error_exit("%s: Check line %d\n", TT.name, TT.linecount);
+ if (TT.lines && compare_keys((void *)&TT.lines, &line)>-!!FLAG(u))
+ error_exit("%s: Check line %u\n", TT.name, TT.linecount);
free(TT.lines);
TT.lines = (void *)line;
} else {
@@ -310,7 +304,9 @@ static void sort_read(int fd, char *name)
void sort_main(void)
{
- int idx, fd = 1;
+ int idx, jdx, fd = 1;
+
+ if (FLAG(u)) toys.optflags |= FLAG_s;
// Parse -k sort keys.
if (TT.k) {
@@ -318,39 +314,32 @@ void sort_main(void)
for (arg = TT.k; arg; arg = arg->next) {
struct sort_key *key = add_key();
- char *temp;
+ char *temp, *temp2, *optlist;
int flag;
idx = 0;
temp = arg->arg;
while (*temp) {
// Start of range
- key->range[2*idx] = (unsigned)strtol(temp, &temp, 10);
- if (*temp=='.')
- key->range[(2*idx)+1] = (unsigned)strtol(temp+1, &temp, 10);
+ key->range[2*idx] = strtol(temp, &temp, 10);
+ if (*temp=='.') key->range[(2*idx)+1] = strtol(temp+1, &temp, 10);
// Handle flags appended to a key type.
for (;*temp;temp++) {
- char *temp2, *optlist;
-
- // Note that a second comma becomes an "Unknown key" error.
+ // Second comma becomes an "Unknown key" error.
if (*temp==',' && !idx++) {
temp++;
break;
}
// Which flag is this?
-
optlist = toys.which->options;
temp2 = strchr(optlist, *temp);
- flag = (1<<(optlist-temp2+strlen(optlist)-1));
+ 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)))
- {
+ if (!temp2 || flag>FLAG_x || (flag&(FLAG_u|FLAG_c|FLAG_s|FLAG_z))) {
toys.exitval = 2;
error_exit("Unknown key option.");
}
@@ -380,11 +369,8 @@ void sort_main(void)
// handle unique (-u)
if (FLAG(u)) {
- int jdx;
-
for (jdx=0, idx=1; idx<TT.linecount; idx++) {
- if (!compare_keys(&TT.lines[jdx], &TT.lines[idx]))
- free(TT.lines[idx]);
+ if (!compare_keys(&TT.lines[jdx], &TT.lines[idx])) free(TT.lines[idx]);
else TT.lines[++jdx] = TT.lines[idx];
}
if (TT.linecount) TT.linecount = jdx+1;
diff --git a/toys/posix/time.c b/toys/posix/time.c
index 951a53d7..1becad1b 100644
--- a/toys/posix/time.c
+++ b/toys/posix/time.c
@@ -26,33 +26,28 @@ config TIME
void time_main(void)
{
- struct timeval tv, tv2;
+ struct timespec ts, ts2;
struct rusage ru;
long long sec[3];
int stat, ii, idx, nano[3];
pid_t pid;
- char *label[] = {"\nreal"+!!FLAG(p), "user", "sys"},
- tab = toys.optflags ? ' ' : '\t';
+ char *labels[] = {"\nreal"+!!FLAG(p), "user", "sys"}, **label = labels,
+ *vlabels[] ={"Real", "User", "System"}, tab = toys.optflags ? ' ' : '\t';
- if (FLAG(v))
- memcpy(label, (char *[]){"Real", "User", "System"}, 3*sizeof(char *));
- gettimeofday(&tv, NULL);
+ if (FLAG(v)) label = vlabels;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
if (!(pid = XVFORK())) xexec(toys.optargs);
wait4(pid, &stat, 0, &ru);
- gettimeofday(&tv2, NULL);
- if (tv.tv_usec > tv2.tv_usec) {
- tv2.tv_usec += 1000000;
- tv2.tv_sec--;
- }
- sec[0] = tv2.tv_sec-tv.tv_sec, nano[0] = tv2.tv_usec-tv.tv_usec;
+ clock_gettime(CLOCK_MONOTONIC, &ts2);
+ sec[0] = nanodiff(&ts, &ts2);
+ nano[0] = (sec[0] % 1000000000)/(toys.optflags ? 1000 : 1000000);
+ sec[0] /= 1000000000;
sec[1] = ru.ru_utime.tv_sec, nano[1] = ru.ru_utime.tv_usec;
sec[2] = ru.ru_stime.tv_sec, nano[2] = ru.ru_stime.tv_usec;
- for (ii = idx = 0; ii<3; ii++) {
- if (!toys.optflags) sec[ii] = (sec[ii]+500)/1000;
+ for (ii = idx = 0; ii<3; ii++)
idx += sprintf(toybuf+idx, "%s%s%c%lld.%0*d\n", label[ii],
FLAG(v) ? " time (s):" : "", tab, sec[ii],
- 3<<!!toys.optflags, nano[ii]);
- }
+ 6>>!toys.optflags, nano[ii]);
if (FLAG(v)) idx += sprintf(toybuf+idx,
"Max RSS (KiB): %ld\nMajor faults: %ld\n"
"Minor faults: %ld\nFile system inputs: %ld\nFile system outputs: %ld\n"
diff --git a/www/ext2.html b/www/doc/ext2.html
index 28bd6cd5..28bd6cd5 100644
--- a/www/ext2.html
+++ b/www/doc/ext2.html
diff --git a/www/doc/mount.html b/www/doc/mount.html
new file mode 100644
index 00000000..89362652
--- /dev/null
+++ b/www/doc/mount.html
@@ -0,0 +1,196 @@
+<h2>How mount actually works</h2>
+
+<p>The <a href=https://landley.net/toybox/help.html#mount>mount comand</a>
+calls the <a href=https://man7.org/linux/man-pages/man2/mount.2.html>mount
+system call</a>, which has five arguments:</p>
+
+<blockquote><b>
+int mount(const char *source, const char *target, const char *filesystemtype,
+ unsigned long mountflags, const void *data);
+</b></blockquote>
+
+<p>The command "<b>mount -t ext2 /dev/sda1 /path/to/mntpoint -o ro,noatime</b>"
+parses its command line arguments to feed them into those five system call
+arguments. In this example, the <b>source</b> is "/dev/sda1", the <b>target</b>
+is "/path/to/mountpoint", and the <b>filesystemtype</b> is "ext2".
+
+<p>The other two syscall arguments (<b>mountflags</b> and </b>data</b>)
+come from the "-o option,option,option" argument. The mountflags argument goes
+to the VFS (explained below), and the data argument is passed to the filesystem
+driver.</p>
+
+<p>The mount command's options string is a list of comma separated values. If
+there's more than one -o argument on the mount command line, they get glued
+together (in order) with a comma. The mount command also checks the file
+<b>/etc/fstab</b> for default options, and the options you specify on the command
+line get appended to those defaults (if any). Most other command line mount
+flags are just synonyms for adding option flags (for example
+"mount -o remount -w" is equivalent to "mount -o remount,rw"). Behind the
+scenes they all get appended to the -o string and fed to a common parser.</p>
+
+<p>VFS stands for "Virtual File System" and is the common infrastructure shared
+by different filesystems. It handles common things like making the filesystem
+read only. The mount command assembles an option string to supply to the "data"
+argument of the option syscall, but first it parses it for VFS options
+(ro,noexec,nodev,nosuid,noatime...) each of which corresponds to a flag
+from <b>#include &lt;sys/mount.h&gt;</b>. The mount command removes those options
+from the string and sets the corresponding bit in mountflags, then the
+remaining options (if any) form the data argument for the filesystem driver.</p>
+
+<blockquote>
+<p>Implementation details: the mountflag MS_SILENCE gets set by
+default even if there's nothing in /etc/fstab. Some actions (such as --bind
+and --move mounts, I.E. -o bind and -o move) are just VFS actions and don't
+require any specific filesystem at all. The "-o remount" flag requires looking
+up the filesystem in /proc/mounts and reassembling the full option string
+because you don't _just_ pass in the changed flags but have to reassemble
+the complete new filesystem state to give the system call. Some of the options
+in /etc/fstab are for the mount command (such as "user" which only does
+anything if the mount command has the suid bit set) and don't get passed
+through to the system call.</p>
+</blockquote>
+
+<p>When mounting a new filesystem, the "<b>filesystem</b>" argument to the mount system
+call specifies which filesystem driver to use. All the loaded drivers are
+listed in /proc/filesystems, but calling mount can also trigger a module load
+request to add another. A filesystem driver is responsible for putting files
+and subdirectories under the mount point: any time you open, close, read,
+write, truncate, list the contents of a directory, move, or delete a file,
+you're talking to a filesystem driver to do it. (Or when you call
+ioctl(), stat(), statvfs(), utime()...)</p>
+
+<h2>Four filesystem types (block backed, server backed, ramfs, synthetic).</h2>
+
+<p>Different drivers implement different filesystems, which come in four
+different types: the filesystem's backing store can be a fixed length
+block of storage, the backing store can be some server the driver connects to,
+the files can remain in memory with no backing store,
+or the filesystem driver can algorithmically create the filesystem's contents
+on the fly.</p>
+
+<ol>
+<li><h3>Block device backed filesystems, such as ext2 and vfat.</h3>
+
+<p>This kind of filesystem driver acts as a lens to look at a block device
+through. The source argument for block backed filesystems is a path to a
+block device (such as "/dev/hda1") which stores the contents of the
+filesystem in a fixed length block of sequential storage, with a seperate
+driver providing that block device.</p>
+
+<p>Block backed filesystems are the "conventional" filesystem type most people
+think of when they mount things. The name means that the "backing store"
+(where the data lives when the system is switched off) is on a block device.</p>
+</li>
+
+<li><h3>Server backed filesystems, such as cifs/samba or fuse.</h3>
+
+<p>These drivers convert filesystem operations into a sequential stream of
+bytes, which it can send through a pipe to talk to a program. The filesystem
+server could be a local Filesystem in Userspace daemon (connected to a local
+process through a pipe filehandle), behind a network socket (CIFS and v9fs),
+behind a char device (/dev/ttyS0), and so on. The common attribute is there's
+some program on the other end sending and receiving a sequential bytestream.
+The backing store is a server somewhere, and the filesystem driver is talking
+to a process that reads and writes data in some known protocol.</p>
+
+<p>The source argument for these filesystems indicates where the filesystem
+lives. It's often in a URL-like format for network filesystems, but it's
+really just a blob of data that the filesystem driver understands.</p>
+
+<p>A lot of server backed filesystems want to open their own connection so they
+don't have to pass their data through a persistent local userspace process,
+not really for performance reasons but because in low memory situations a
+chicken-and-egg situation can develop where all the process's pages have
+been swapped out but the filesystem needs to write data to its backing
+store in order to free up memory so it can swap the process's pages back in.
+If this mechanism is providing the root filesystem, this can deadlock and
+freeze the system solid. So while you _can_ pass some of them a filehandle,
+more often than not you don't.</p>
+
+<p>These are also known as "pipe backed" filesystems (or "network filesystems"
+because that's a common case, although a network doesn't need to be inolved).
+Conceptually they're char device backed filesystems analogous to the block
+backed filesystems (block devices provide seekable storage, char devices
+provide serial I/O), but you don't commonly specify a character device in
+/dev when mounting them because you're talking to a specific server process,
+not a whole machine.</p>
+</li>
+
+<li><h3>Ram backed filesystems (ramfs and tmpfs).</h3>
+
+<p>These are very simple filesystems that don't implement a backing store,
+but just keep the data in memory. Data
+written to these gets stored in the disk cache, and the driver ignores requests
+to flush it to backing store (reporting all the pages as pinned and
+unfreeable).</p>
+
+<p>These filesystem drivers essentially mount the VFS's page/dentry cache as if it was a
+filesystem. (Page cache stores file contents, dentry cache stores directory
+entries.) They grow and shrink dynamically as needed: when you write files
+into them they allocate more memory to store it, and when you delete files
+the memory is freed.</p>
+
+<p>The "ramfs" driver provides the simplest possible ram filesystem,
+which is too simple for most real use cases. The "tmpfs" driver adds
+a size limitation (by default 50% of system RAM, but it's adjustable as a mount
+option) so the system doesn't run out of memory and lock up if you
+"cat /dev/zero > file", can report how much space is remaining
+when asked (ramfs always says 0 bytes free), and can write its data
+out to swap space (like processes do) when the system is under memory pressure.</p>
+
+<blockquote>
+<p>Note that "ramdisk" is not the same as "ramfs". The ramdisk driver uses a
+chunk of memory to implement a block device, and then you can format that
+block device and mount it with a block device backed filesystem driver.
+(This is the same "two device drivers" approach you always have with block
+backed filesystems: one driver provides /dev/ram0 and the second driver mounts
+it as vfat.) Ram disks are significantly less efficient than ramfs,
+allocating a fixed amount of memory up front for the block device instead of
+dynamically resizing itself as files are written into an deleted from the
+page and dentry caches the way ramfs does.</p>
+</blockquote>
+
+<p>Initramfs (I.E. rootfs) is a ram backed filesystem mounted on / which
+can't be unmounted for the same reason PID 1 can't exit. The boot
+process can extract a cpio.gz archive into it (either statically linked
+into the kernel or loaded as a second file by the bootloader), and
+if it contains an executable "init" binary at the top level that
+will be run as PID 1. If you specify "root=" on the kernel command line,
+initramfs will be ramfs and will get overmounted with the specified
+filesystem if no "/init" binary can be run out of the initramfs.
+If you don't specify root= then initramfs will be tmpfs, which is probably
+what you want when the system is running from initramfs.</p>
+</li>
+
+<li><h3>Synthetic filesystems (proc, sysfs, devtmpfs, devpts...)</h3>
+
+<p>These filesystems don't have any backing store because they don't
+store arbitrary data the way the first three types of filesystems do.</p>
+
+<p>Instead they present artificial contents, which can represent processes or
+hardware or anything the driver writer wants them to show. Listing or reading
+from these files calls a driver function that produces whatever output it's
+programmed to, and writing to these files submits data to the driver which
+can do anything it wants with it.</p>
+
+<p>Synthetic filesystems are often implemented to provide monitoring and control
+knobs for parts of the operating system, as an alternative to adding more
+system calls (or ioctl, sysctl, etc). They provide a more human friendly user
+interface which programs can use but which users can also interact with
+directly from the command line via "cat" and redirecting the output of
+"echo" into special files.</p>
+
+<blockquote>
+<p>The first synthetic filesystem in Linux was "proc", which was initially
+intended to provide a directory for each process in the system to provide
+information to tools like "ps" and "top" (the /proc/[0-9]* entries)
+but became a dumping ground for any information the kernel wanted to export.
+Eventually the kernel developers <a href=https://lwn.net/Articles/57369/>genericized</a>
+the synthetic filesystem infrastructure so the system could have multiple
+different synthetic filesystems, but /proc remains full
+unrelated historic legacy exports kept for backwards compatibility.</p>
+</blockquote>
+</li>
+</ol>
+
+<p>TODO: explain overmounts, mount --move, mount namespaces.</p>
diff --git a/www/doc/mount.txt b/www/doc/mount.txt
deleted file mode 100644
index f538c467..00000000
--- a/www/doc/mount.txt
+++ /dev/null
@@ -1,163 +0,0 @@
-Here's how mount actually works:
-
-The mount comand calls the mount system call, which has five arguments you
-can see on the "man 2 mount" page:
-
- int mount(const char *source, const char *target, const char *filesystemtype,
- unsigned long mountflags, const void *data);
-
-The command "mount -t ext2 /dev/sda1 /path/to/mntpoint -o ro,noatime",
-parses its command line arguments to feed them into those five system call
-arguments. In this example, the source is "/dev/sda1", the target is
-"/path/to/mountpoint", and the filesystemtype is "ext2".
-
-The other two syscall arguments (mountflags and data) come from the
-"-o option,option,option" argument. The mountflags argument goes to the VFS
-(explained below), and the data argument is passed to the filesystem driver.
-
-The mount command's options string is a list of comma separated values. If
-there's more than one -o argument on the mount command line, they get glued
-together (in order) with a comma. The mount command also checks the file
-/etc/fstab for default options, and the options you specify on the command
-line get appended to those defaults (if any). Most other command line mount
-flags are just synonyms for adding option flags (for example
-"mount -o remount -w" is equivalent to "mount -o remount,rw"). Behind the
-scenes they all get appended to the -o string and fed to a common parser.
-
-VFS stands for "Virtual File System" and is the common infrastructure shared
-by different filesystems. It handles common things like making the filesystem
-read only. The mount command assembles an option string to supply to the "data"
-argument of the option syscall, but first it parses it for VFS options
-(ro,noexec,nodev,nosuid,noatime...) each of which corresponds to a flag
-from #include <sys/mount.h>. The mount command removes those options from the
-sting and sets the corresponding bit in mountflags, then the remaining options
-(if any) form the data argument for the filesystem driver.
-
-A few quick implementation details: the mountflag MS_SILENCE gets set by
-default even if there's nothing in /etc/fstab. Some actions (such as --bind
-and --move mounts, I.E. -o bind and -o move) are just VFS actions and don't
-require any specific filesystem at all. The "-o remount" flag requires looking
-up the filesystem in /proc/mounts and reassembling the full option string
-because you don't _just_ pass in the changed flags but have to reassemble
-the complete new filesystem state to give the system call. Some of the options
-in /etc/fstab are for the mount command (such as "user" which only does
-anything if the mount command has the suid bit set) and don't get passed
-through to the system call.
-
-When mounting a new filesystem, the "filesystem" argument to the mount system
-call specifies which filesystem driver to use. All the loaded drivers are
-listed in /proc/filesystems, but calling mount can also trigger a module load
-request to add another. A filesystem driver is responsible for putting files
-and subdirectories under the mount point: any time you open, close, read,
-write, truncate, list the contents of a directory, move, or delete a file,
-you're talking to a filesystem driver to do it. (Or when you call
-ioctl(), stat(), statvfs(), utime()...)
-
-Different drivers implement different filesystems, which have four categories:
-
-1) Block device backed filesystems, such as ext2 and vfat.
-
-This kind of filesystem driver acts as a lens to look at a block device
-through. The source argument for block backed filesystems is a path to a
-block device, such as "/dev/hda1", which stores the contents of the
-filesystem in a fixed block of sequential storage, and there's a seperate
-driver providing that block device.
-
-Block backed filesystems are the "conventional" filesystem type most people
-think of when they mount things. The name means that the "backing store"
-(where the data lives when the system is switched off) is on a block device.
-
-2) Server backed filesystems, such as cifs/samba or fuse.
-
-These drivers convert filesystem operations into a sequential stream of
-bytes, which it can send through a pipe to talk to a program. The filesystem
-server could be a local Filesystem in Userspace daemon (connected to a local
-process through a pipe filehandle), behind a network socket (CIFS and v9fs),
-behind a char device (/dev/ttyS0), and so on. The common attribute is there's
-some program on the other end sending and receiving a sequential bytestream.
-The backing store is a server somewhere, and the filesystem driver is talking
-to a process that reads and writes data in some known protocol.
-
-The source argument for these filesystems indicates where the filesystem lives. It's often in a URL-like format for network filesystems, but it's really just a blob of data that the filesystem driver understands.
-
-A lot of server backed filesystems want to open their own connection so they
-don't have to pass their data through a persistent local userspace process,
-not really for performance reasons but because in low memory situations a
-chicken-and-egg situation can develop where all the process's pages have
-been swapped out but the filesystem needs to write data to its backing
-store in order to free up memory so it can swap the process's pages back in.
-If this mechanism is providing the root filesystem, this can deadlock and
-freeze the system solid. So while you _can_ pass some of them a filehandle,
-more often than not you don't.
-
-These are also known as "pipe backed" filesystems (or "network filesystems"
-because that's a common case, although a network doesn't need to be inolved).
-Conceptually they're char device backed filesystems (analogus to the block
-device backed ones), but you don't commonly specify a character device in
-/dev when mounting them because you're talking to a specific server process,
-not a whole machine.
-
-3) Ram backed filesystems, such as ramfs and tmpfs.
-
-These are very simple filesystems that don't implement a backing store. Data
-written to these gets stored in the disk cache, and the driver ignores requests
-to flush it to backing store (reporting all the pages as pinned and
-unfreeable).
-
-These drivers essentially mount the VFS's page/dentry cache as if it was a
-filesystem. (Page cache stores file contents, dentry cache stores directory
-entries.) They grow and shrink dynamically, as needed: when you write files
-into them they allocate more memory to store it, and when you delete files
-the memory is freed.
-
-There's a simple one (ramfs) that does only that, and a more complex one (tmpfs)
-which adds a size limitation (by default 50%, but it's adjustable as a mount
-option) so the system doesn't run out of memory and lock up if you
-"cat /dev/zero > file", and can also report how much space is remaining
-when asked (ramfs always says 0 bytes free). The other thing tmpfs does
-is write its data out to swap space (like processes do) when the system
-is under memory proessure.
-
-Note that "ramdisk" is not the same as "ramfs". The ramdisk driver uses a
-chunk of memory to implement a block device, and then you can format that
-block device and mount it with a block device backed filesystem driver.
-(This is the same "two device drivers" approach you always have with block
-backed filesystems: one driver provides /dev/ram0 and the second driver mounts
-it as vfat.) Ram disks are significantly less efficient than ramfs,
-allocating a fixed amount of memory up front for the block device instead of
-dynamically resizing itself as files are written into an deleted from the
-page and dentry caches the way ramfs does.
-
-Note: initramfs cpio, tmpfs as rootfs.
-
-4) Synthetic filesystems, such as proc, sysfs, devpts...
-
-These filesystems don't have any backing store either, because they don't
-store arbitrary data the way the first three types of filesystems do.
-
-Instead they present artificial contents, which can represent processes or
-hardware or anything the driver writer wants them to show. Listing or reading
-from these files calls a driver function that produces whatever output it's
-programmed to, and writing to these files submits data to the driver which
-can do anything it wants with it.
-
-Synthetic ilesystems are often implemented to provide monitoring and control
-knobs for parts of the operating system. It's an alternative to adding more
-system calls (or ioctl, sysctl, etc), and provides a more human friendly user
-interface which programs can use but which users can also interact with
-directly from the command line via "cat" and redirecting the output of
-"echo" into special files.
-
-
-Those are the four types of filesystems: backing store can be a fixed length
-block of storage, backing store can be some server the driver connects to,
-backing store can not exist and the files merely reside in the disk cache,
-or the filesystem driver can just make up its contents programmatically.
-
-And that's how filesystems get mounted, using the mount system call which has
-five arguments. The "filesystem" argument specifies the driver implementing
-one of those filesystems, and the "source" and "data" arguments get fed to
-that driver. The "target" and "mountflags" arguments get parsed (and handled)
-by the generic VFS infrastructure. (The filesystem driver can peek at the
-VFS data, but generally doesn't need to care. The VFS tells the filesystem
-what to do, in response to what userspace said to do.)
diff --git a/www/news.html b/www/news.html
index dfe71caf..cc85450e 100644
--- a/www/news.html
+++ b/www/news.html
@@ -387,7 +387,7 @@ when wordwrapping (previously hardwired to 80 columns).
If you're curious, I checked in my <a href=www/release.txt>release procedure
checklist</a>, and
fixed a stale link in the nav bar on the left ("statistics" changed domains).
-Firas Khaliki Khana fixed some issues in the roadmap, and Rob
+Firas Khalil Khana fixed some issues in the roadmap, and Rob
tweaked the roadmap so status.html is slightly more current.</p>
<p><u>Tests</u>: