diff options
author | Elliott Hughes <enh@google.com> | 2022-01-20 12:12:33 -0800 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2022-01-20 12:52:14 -0800 |
commit | e95470fb07c7cf56209ad3042485c324c91b0729 (patch) | |
tree | 649cf9f8c345e11369ff685a33a7b6af196408a7 | |
parent | ed6451c5a0d9c76178ed066edbe3d7d65e0a3930 (diff) | |
parent | e7e4229c059f4a45eaf0ff0cb0f228275e3e7772 (diff) | |
download | toybox-e95470fb07c7cf56209ad3042485c324c91b0729.tar.gz |
Upgrade toybox to e7e4229c059f4a45eaf0ff0cb0f228275e3e7772
Test: make
Change-Id: Ie5a3e5de1ef654d46e0f411dabc22adf89bc61fc
67 files changed, 837 insertions, 766 deletions
@@ -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)) @@ -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" @@ -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, @@ -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? @@ -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' @@ -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 <sys/mount.h></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>: |