aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2018-02-08 19:36:59 +0000
committerandroid-build-merger <android-build-merger@google.com>2018-02-08 19:36:59 +0000
commit7f1d01238d50e387c99e71e19090b67799100f31 (patch)
tree390dcafecae493658ea620f1e2a5802ac9afb7c1
parentba229b4bff5f4a9ebef4a35539911f01706c0b13 (diff)
parentb02120dad8b5e4e7f65d97bc73a3c2b74de0f4ee (diff)
downloadtoybox-7f1d01238d50e387c99e71e19090b67799100f31.tar.gz
Merge remote-tracking branch 'toybox/master' into HEAD
am: b02120dad8 Change-Id: I1295c7bd2156f093e702fd2196dc222bf43b2a48
-rw-r--r--.config1
-rwxr-xr-x[-rw-r--r--]configure11
-rw-r--r--generated/config.h2
-rw-r--r--generated/flags.h36
-rw-r--r--generated/globals.h14
-rw-r--r--generated/help.h6
-rw-r--r--generated/newtoys.h3
-rw-r--r--lib/lib.h1
-rw-r--r--lib/net.c13
-rw-r--r--toys/pending/ping.c221
-rw-r--r--toys/posix/cksum.c28
-rw-r--r--toys/posix/ps.c2
12 files changed, 264 insertions, 74 deletions
diff --git a/.config b/.config
index 22616a47..d0de7b0a 100644
--- a/.config
+++ b/.config
@@ -72,6 +72,7 @@ CONFIG_CPIO=y
CONFIG_CP_MORE=y
CONFIG_CP_PRESERVE=y
CONFIG_CP=y
+# CONFIG_CRC32 is not set
# CONFIG_CROND is not set
# CONFIG_CRONTAB is not set
CONFIG_CUT=y
diff --git a/configure b/configure
index a7a427f6..14c9c659 100644..100755
--- a/configure
+++ b/configure
@@ -1,7 +1,16 @@
-# Toybox configuration file.
+#!/bin/bash
# This sets environment variables used by scripts/make.sh
+# People run ./configure out of habit, so do "defconfig" for them.
+
+if [ "$(basename "$0")" == configure ]
+then
+ echo "Assuming you want 'make defconfig', but you should probably check the README."
+ make defconfig
+ exit $?
+fi
+
# A synonym.
[ -z "$CROSS_COMPILE" ] && CROSS_COMPILE="$CROSS"
diff --git a/generated/config.h b/generated/config.h
index 8f4f1130..79da5e6e 100644
--- a/generated/config.h
+++ b/generated/config.h
@@ -118,6 +118,8 @@
#define USE_CP_PRESERVE(...) __VA_ARGS__
#define CFG_CP 1
#define USE_CP(...) __VA_ARGS__
+#define CFG_CRC32 0
+#define USE_CRC32(...)
#define CFG_CROND 0
#define USE_CROND(...)
#define CFG_CRONTAB 0
diff --git a/generated/flags.h b/generated/flags.h
index e0c24f35..7e2ba200 100644
--- a/generated/flags.h
+++ b/generated/flags.h
@@ -375,6 +375,14 @@
#undef FLAG_no_preserve_owner
#endif
+// crc32
+#undef OPTSTR_crc32
+#define OPTSTR_crc32 0
+#ifdef CLEANUP_crc32
+#undef CLEANUP_crc32
+#undef FOR_crc32
+#endif
+
// crond fbSl#<0=8d#<0L:c:[-bf][-LS][-ld]
#undef OPTSTR_crond
#define OPTSTR_crond "fbSl#<0=8d#<0L:c:[-bf][-LS][-ld]"
@@ -1955,17 +1963,19 @@
#undef FLAG_s
#endif
-// ping <1>1t#<0>255c#<0s#<0>65535I:W#<0w#<0q46[-46]
+// ping <1>1t#<0>255=64c#<0=3s#<0>4088=56I:i:W#<0=10w#<0qf46[-46]
#undef OPTSTR_ping
-#define OPTSTR_ping "<1>1t#<0>255c#<0s#<0>65535I:W#<0w#<0q46[-46]"
+#define OPTSTR_ping "<1>1t#<0>255=64c#<0=3s#<0>4088=56I:i:W#<0=10w#<0qf46[-46]"
#ifdef CLEANUP_ping
#undef CLEANUP_ping
#undef FOR_ping
#undef FLAG_6
#undef FLAG_4
+#undef FLAG_f
#undef FLAG_q
#undef FLAG_w
#undef FLAG_W
+#undef FLAG_i
#undef FLAG_I
#undef FLAG_s
#undef FLAG_c
@@ -3572,6 +3582,12 @@
#define FLAG_no_preserve_owner (1<<11)
#endif
+#ifdef FOR_crc32
+#ifndef TT
+#define TT this.crc32
+#endif
+#endif
+
#ifdef FOR_crond
#ifndef TT
#define TT this.crond
@@ -4912,13 +4928,15 @@
#endif
#define FLAG_6 (FORCED_FLAG<<0)
#define FLAG_4 (FORCED_FLAG<<1)
-#define FLAG_q (FORCED_FLAG<<2)
-#define FLAG_w (FORCED_FLAG<<3)
-#define FLAG_W (FORCED_FLAG<<4)
-#define FLAG_I (FORCED_FLAG<<5)
-#define FLAG_s (FORCED_FLAG<<6)
-#define FLAG_c (FORCED_FLAG<<7)
-#define FLAG_t (FORCED_FLAG<<8)
+#define FLAG_f (FORCED_FLAG<<2)
+#define FLAG_q (FORCED_FLAG<<3)
+#define FLAG_w (FORCED_FLAG<<4)
+#define FLAG_W (FORCED_FLAG<<5)
+#define FLAG_i (FORCED_FLAG<<6)
+#define FLAG_I (FORCED_FLAG<<7)
+#define FLAG_s (FORCED_FLAG<<8)
+#define FLAG_c (FORCED_FLAG<<9)
+#define FLAG_t (FORCED_FLAG<<10)
#endif
#ifdef FOR_pivot_root
diff --git a/generated/globals.h b/generated/globals.h
index c5ddadd9..6f01070b 100644
--- a/generated/globals.h
+++ b/generated/globals.h
@@ -765,14 +765,16 @@ struct openvt_data {
// toys/pending/ping.c
struct ping_data {
- long wait_exit;
- long wait_resp;
- char *iface;
- long size;
- long count;
- long ttl;
+ long w;
+ long W;
+ char *i;
+ char *I;
+ long s;
+ long c;
+ long t;
int sock;
+ long i_ms;
};
// toys/pending/route.c
diff --git a/generated/help.h b/generated/help.h
index f648b83c..d38c4d21 100644
--- a/generated/help.h
+++ b/generated/help.h
@@ -336,7 +336,7 @@
#define HELP_route "usage: route [-ne] [-A [46]] [add|del TARGET [OPTIONS]]\n\nDisplay, add or delete network routes in the \"Forwarding Information Base\".\n\n-n Show numerical addresses (no DNS lookups)\n-e display netstat fields\n\nRouting means sending packets out a network interface to an address.\nThe kernel can tell where to send packets one hop away by examining each\ninterface's address and netmask, so the most common use of this command\nis to identify a \"gateway\" that forwards other traffic.\n\nAssigning an address to an interface automatically creates an appropriate\nnetwork route (\"ifconfig eth0 10.0.2.15/8\" does \"route add 10.0.0.0/8 eth0\"\nfor you), although some devices (such as loopback) won't show it in the\ntable. For machines more than one hop away, you need to specify a gateway\n(ala \"route add default gw 10.0.2.2\").\n\nThe address \"default\" is a wildcard address (0.0.0.0/0) matching all\npackets without a more specific route.\n\nAvailable OPTIONS include:\nreject - blocking route (force match failure)\ndev NAME - force packets out this interface (ala \"eth0\")\nnetmask - old way of saying things like ADDR/24\ngw ADDR - forward packets to gateway ADDR\n\n\n"
-#define HELP_ping "usage: ping [OPTIONS] HOST\n\nCheck network connectivity by sending packets to a host and reporting\nits response.\n\nSend ICMP ECHO_REQUEST packets to ipv4 or ipv6 addresses and prints each\necho it receives back, with round trip time.\n\nOptions:\n-4, -6 Force IPv4 or IPv6\n-c CNT Send CNT many packets\n-I IFACE/IP Source interface or address\n-q Quiet, only displays output at start and when finished\n-s SIZE Packet SIZE in bytes (default 56)\n-t TTL Set Time (number of hops) To Live\n-W SEC Seconds to wait for response after all packets sent (default 10)\n-w SEC Exit after this many seconds\n\n"
+#define HELP_ping "usage: ping [OPTIONS] HOST\n\nCheck network connectivity by sending packets to a host and reporting\nits response.\n\nSend ICMP ECHO_REQUEST packets to ipv4 or ipv6 addresses and prints each\necho it receives back, with round trip time. Returns true if host alive.\n\nOptions:\n-4, -6 Force IPv4 or IPv6\n-c CNT Send CNT many packets (default 3, 0 = infinite)\n-f Flood (. on send, backspace on receive, to show packet drops)\n-i TIME Interval between packets (default 1, need root for < .2)\n-I IFACE/IP Source interface or address\n-q Quiet (stops after one returns true if host is alive)\n-s SIZE Data SIZE in bytes (default 56)\n-t TTL Set Time To Live (number of hops)\n-W SEC Seconds to wait for response after -c (default 10)\n-w SEC Exit after this many seconds\n\n"
#define HELP_deallocvt "usage: deallocvt [N]\n\nDeallocate unused virtual terminal /dev/ttyN, or all unused consoles.\n\n"
@@ -576,7 +576,9 @@
#define HELP_cmp "usage: cmp [-l] [-s] FILE1 FILE2\n\nCompare the contents of two files.\n\n-l show all differing bytes\n-s silent\n\n"
-#define HELP_cksum "usage: cksum [-IPLN] [file...]\n\nFor each file, output crc32 checksum value, length and name of file.\nIf no files listed, copy from stdin. Filename \"-\" is a synonym for stdin.\n\n-H Hexadecimal checksum (defaults to decimal)\n-L Little endian (defaults to big endian)\n-P Pre-inversion\n-I Skip post-inversion\n-N Do not include length in CRC calculation\n\n"
+#define HELP_crc32 "usage: crc32 [file...]\n\nOutput crc32 checksum for each file.\n\n"
+
+#define HELP_cksum "usage: cksum [-IPLN] [file...]\n\nFor each file, output crc32 checksum value, length and name of file.\nIf no files listed, copy from stdin. Filename \"-\" is a synonym for stdin.\n\n-H Hexadecimal checksum (defaults to decimal)\n-L Little endian (defaults to big endian)\n-P Pre-inversion\n-I Skip post-inversion\n-N Do not include length in CRC calculation (or output)\n\n"
#define HELP_chmod "usage: chmod [-R] MODE FILE...\n\nChange mode of listed file[s] (recursively with -R).\n\nMODE can be (comma-separated) stanzas: [ugoa][+-=][rwxstXugo]\n\nStanzas are applied in order: For each category (u = user,\ng = group, o = other, a = all three, if none specified default is a),\nset (+), clear (-), or copy (=), r = read, w = write, x = execute.\ns = u+s = suid, g+s = sgid, o+s = sticky. (+t is an alias for o+s).\nsuid/sgid: execute as the user/group who owns the file.\nsticky: can't delete files you don't own out of this directory\nX = x for directories or if any category already has x set.\n\nOr MODE can be an octal value up to 7777 ug uuugggooo top +\nbit 1 = o+x, bit 1<<8 = u+w, 1<<11 = g+1 sstrwxrwxrwx bottom\n\nExamples:\nchmod u+w file - allow owner of \"file\" to write to it.\nchmod 744 file - user can read/write/execute, everyone else read only\n\n"
diff --git a/generated/newtoys.h b/generated/newtoys.h
index 6743a3b7..0c7fbb3e 100644
--- a/generated/newtoys.h
+++ b/generated/newtoys.h
@@ -36,6 +36,7 @@ USE_COMPRESS(NEWTOY(compress, "zcd9lrg[-cd][!zgLr]", TOYFLAG_USR|TOYFLAG_BIN))
USE_COUNT(NEWTOY(count, NULL, TOYFLAG_USR|TOYFLAG_BIN))
USE_CP(NEWTOY(cp, "<2"USE_CP_PRESERVE("(preserve):;")"RHLPprdaslvnF(remove-destination)fi[-HLPd][-ni]", TOYFLAG_BIN))
USE_CPIO(NEWTOY(cpio, "(no-preserve-owner)(trailer)mduH:p:|i|t|F:v(verbose)o|[!pio][!pot][!pF]", TOYFLAG_BIN))
+USE_CRC32(NEWTOY(crc32, 0, TOYFLAG_BIN))
USE_CROND(NEWTOY(crond, "fbSl#<0=8d#<0L:c:[-bf][-LS][-ld]", TOYFLAG_USR|TOYFLAG_SBIN|TOYFLAG_NEEDROOT))
USE_CRONTAB(NEWTOY(crontab, "c:u:elr[!elr]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_STAYROOT))
USE_CUT(NEWTOY(cut, "b*|c*|f*|F*|C*|O(output-delimiter):d:sDn[!cbf]", TOYFLAG_USR|TOYFLAG_BIN))
@@ -172,7 +173,7 @@ USE_PASTE(NEWTOY(paste, "d:s", TOYFLAG_BIN|TOYFLAG_LOCALE))
USE_PATCH(NEWTOY(patch, "(dry-run)"USE_TOYBOX_DEBUG("x")"d:ulp#i:R", TOYFLAG_USR|TOYFLAG_BIN))
USE_PGREP(NEWTOY(pgrep, "?cld:u*U*t*s*P*g*G*fnovxL:[-no]", TOYFLAG_USR|TOYFLAG_BIN))
USE_PIDOF(NEWTOY(pidof, "<1so:", TOYFLAG_BIN))
-USE_PING(NEWTOY(ping, "<1>1t#<0>255c#<0s#<0>65535I:W#<0w#<0q46[-46]", TOYFLAG_ROOTONLY|TOYFLAG_USR|TOYFLAG_BIN))
+USE_PING(NEWTOY(ping, "<1>1t#<0>255=64c#<0=3s#<0>4088=56I:i:W#<0=10w#<0qf46[-46]", TOYFLAG_ROOTONLY|TOYFLAG_USR|TOYFLAG_BIN))
USE_PIVOT_ROOT(NEWTOY(pivot_root, "<2>2", TOYFLAG_SBIN))
USE_PKILL(NEWTOY(pkill, "?Vu*U*t*s*P*g*G*fnovxl:[-no]", TOYFLAG_USR|TOYFLAG_BIN))
USE_PMAP(NEWTOY(pmap, "<1xq", TOYFLAG_BIN))
diff --git a/lib/lib.h b/lib/lib.h
index 94662983..939d6127 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -294,6 +294,7 @@ struct addrinfo *xgetaddrinfo(char *host, char *port, int family, int socktype,
int xconnect(struct addrinfo *ai_arg);
int xpoll(struct pollfd *fds, int nfds, int timeout);
int pollinate(int in1, int in2, int out1, int out2, int timeout, int shutdown_timeout);
+char *ntop(struct sockaddr *sa);
// password.c
int get_salt(char *salt, char * algo);
diff --git a/lib/net.c b/lib/net.c
index 5c6d4f7c..846be31f 100644
--- a/lib/net.c
+++ b/lib/net.c
@@ -102,3 +102,16 @@ int pollinate(int in1, int in2, int out1, int out2, int timeout, int shutdown_ti
}
}
}
+
+// Return converted numeric address in libbuf
+char *ntop(struct sockaddr *sa)
+{
+ void *addr;
+
+ if (sa->sa_family == AF_INET) addr = &((struct sockaddr_in *)sa)->sin_addr;
+ else addr = &((struct sockaddr_in6 *)sa)->sin6_addr;
+
+ inet_ntop(sa->sa_family, addr, libbuf, sizeof(libbuf));
+
+ return libbuf;
+}
diff --git a/toys/pending/ping.c b/toys/pending/ping.c
index 545ad79c..3802918d 100644
--- a/toys/pending/ping.c
+++ b/toys/pending/ping.c
@@ -3,8 +3,14 @@
* Copyright 2014 Rob Landley <rob@landley.net>
*
* Not in SUSv4.
+ *
+ * Note: ping_group_range should never have existed. To disable it, do:
+ * echo 0 $(((1<<31)-1)) > /proc/sys/net/ipv4/ping_group_range
+ * (Android does this by default in its init script.)
+ *
+ * Yes, I wimped out and capped -s at sizeof(toybuf), waiting for a complaint...
-USE_PING(NEWTOY(ping, "<1>1t#<0>255c#<0s#<0>65535I:W#<0w#<0q46[-46]", TOYFLAG_ROOTONLY|TOYFLAG_USR|TOYFLAG_BIN))
+USE_PING(NEWTOY(ping, "<1>1t#<0>255=64c#<0=3s#<0>4088=56I:i:W#<0=10w#<0qf46[-46]", TOYFLAG_ROOTONLY|TOYFLAG_USR|TOYFLAG_BIN))
config PING
bool "ping"
@@ -16,16 +22,18 @@ config PING
its response.
Send ICMP ECHO_REQUEST packets to ipv4 or ipv6 addresses and prints each
- echo it receives back, with round trip time.
+ echo it receives back, with round trip time. Returns true if host alive.
Options:
-4, -6 Force IPv4 or IPv6
- -c CNT Send CNT many packets
+ -c CNT Send CNT many packets (default 3, 0 = infinite)
+ -f Flood (. on send, backspace on receive, to show packet drops)
+ -i TIME Interval between packets (default 1, need root for < .2)
-I IFACE/IP Source interface or address
- -q Quiet, only displays output at start and when finished
- -s SIZE Packet SIZE in bytes (default 56)
- -t TTL Set Time (number of hops) To Live
- -W SEC Seconds to wait for response after all packets sent (default 10)
+ -q Quiet (stops after one returns true if host is alive)
+ -s SIZE Data SIZE in bytes (default 56)
+ -t TTL Set Time To Live (number of hops)
+ -W SEC Seconds to wait for response after -c (default 10)
-w SEC Exit after this many seconds
*/
@@ -33,23 +41,44 @@ config PING
#include "toys.h"
#include <ifaddrs.h>
+#include <netinet/ip_icmp.h>
GLOBALS(
- long wait_exit;
- long wait_resp;
- char *iface;
- long size;
- long count;
- long ttl;
+ long w;
+ long W;
+ char *i;
+ char *I;
+ long s;
+ long c;
+ long t;
int sock;
+ long i_ms;
)
-void *sock2addr(struct sockaddr *sa)
+static void xsendto(int sockfd, void *buf, size_t len, struct sockaddr *dest)
+{
+ int rc = sendto(TT.sock, buf, len, 0, dest,
+ dest->sa_family == AF_INET ? sizeof(struct sockaddr_in) :
+ sizeof(struct sockaddr_in6));
+
+ if (rc != len) perror_exit("sendto");
+}
+
+// assumes aligned and can read even number of bytes
+static unsigned short pingchksum(unsigned short *data, int len)
{
- if (sa->sa_family == AF_INET)
- return &((struct sockaddr_in *)sa)->sin_addr;
- return &((struct sockaddr_in6 *)sa)->sin6_addr;
+ unsigned short u = 0, d;
+
+ // circular carry is endian independent: bits from high byte go to low byte
+ while (len>0) {
+ d = *data++;
+ if (len == 1) d &= 255<<IS_BIG_ENDIAN;
+ if (d >= (u += d)) u++;
+ len -= 2;
+ }
+
+ return u;
}
void ping_main(void)
@@ -59,41 +88,55 @@ void ping_main(void)
union {
struct sockaddr_in in;
struct sockaddr_in6 in6;
- } src_addr;
- struct sockaddr *sa = (void *)&src_addr;
- int family = 0;
-
- // no 4/6 specified: -I has only one, arg must match
- // no 4/6 specified: arg is one, -I must match
- // 4/6 specified, both must match
-
- if (!(toys.optflags&FLAG_s)) TT.size = 56; // 64-PHDR_LEN
+ } src_addr, src_addr2;
+ struct sockaddr *sa = (void *)&src_addr, *sa2 = (void *)&src_addr2;
+ struct pollfd pfd;
+ int family = 0, sent = 0, len;
+ long long tnext, tW, tnow, tw;
+ unsigned short seq = 0;
+ struct icmphdr *ih = (void *)toybuf;
+
+ // Interval
+ if (TT.i) {
+ long frac;
+
+ TT.i_ms = xparsetime(TT.i, 1000, &frac) * 1000;
+ TT.i_ms += frac;
+ if (TT.i_ms<200 && getuid()) error_exit("need root for -i <200");
+ } else TT.i_ms = 1000;
+ if (!(toys.optflags&FLAG_s)) TT.s = 56; // 64-PHDR_LEN
+
+ // ipv4 or ipv6? (0 = autodetect if -I or arg have only one address type.)
if (toys.optflags&FLAG_6) family = AF_INET6;
else if (toys.optflags&FLAG_4) family = AF_INET;
else family = 0;
// If -I src_addr look it up. Allow numeric address of correct type.
memset(&src_addr, 0, sizeof(src_addr));
- if (TT.iface) {
- if (!(toys.optflags&FLAG_6) && inet_pton(AF_INET, TT.iface,
+ if (TT.I) {
+ if (!(toys.optflags&FLAG_6) && inet_pton(AF_INET, TT.I,
(void *)&src_addr.in.sin_addr))
- family = sa->sa_family = AF_INET;
- else if (!(toys.optflags&FLAG_4) && inet_pton(AF_INET6, TT.iface,
+ family = AF_INET;
+ else if (!(toys.optflags&FLAG_4) && inet_pton(AF_INET6, TT.I,
(void *)&src_addr.in6.sin6_addr))
- family = sa->sa_family = AF_INET6;
+ family = AF_INET6;
else if (getifaddrs(&ifa2)) perror_exit("getifaddrs");
}
- // Look up HOST address, filtering for correct type.
+ // Look up HOST address, filtering for correct type and interface.
// If -I but no -46 then find compatible type between -I and HOST
- ai2 = xgetaddrinfo(toys.optargs[0], 0, family, 0, 0, 0);
+ ai2 = xgetaddrinfo(*toys.optargs, 0, family, 0, 0, 0);
for (ai = ai2; ai; ai = ai->ai_next) {
+
+ // correct type?
if (family && family!=ai->ai_family) continue;
if (ai->ai_family!=AF_INET && ai->ai_family!=AF_INET6) continue;
- if (!TT.iface || !ifa2) break;
+
+ // correct interface?
+ if (!TT.I || !ifa2) break;
for (ifa = ifa2; ifa; ifa = ifa->ifa_next) {
if (!ifa->ifa_addr || ifa->ifa_addr->sa_family!=ai->ai_family
- || strcmp(ifa->ifa_name, TT.iface)) continue;
+ || strcmp(ifa->ifa_name, TT.I)) continue;
sa = (void *)ifa->ifa_addr;
break;
@@ -102,19 +145,101 @@ void ping_main(void)
}
if (!ai)
- error_exit("no v%d addr for -I %s", 4+2*(family==AF_INET6), TT.iface);
-
- inet_ntop(family, sock2addr(sa), toybuf, sizeof(toybuf));
- printf("host=%s\n", toybuf);
- *toybuf = 0;
- inet_ntop(ai->ai_family, sock2addr(ai->ai_addr), toybuf, sizeof(toybuf));
- printf("targ=%s\n", toybuf);
-
- // Open raw socket
- TT.sock = xsocket(ai->ai_family, SOCK_DGRAM, (ifa->ifa_addr->sa_family == AF_INET) ?
- IPPROTO_ICMP : IPPROTO_ICMPV6);
- if (TT.iface && bind(TT.sock, ifa->ifa_addr, sizeof(src_addr)))
- perror_exit("bind");
+ error_exit("no v%d addr for -I %s", 4+2*(family==AF_INET6), TT.I);
+
+ // Open DGRAM socket
+ sa->sa_family = ai->ai_family;
+ TT.sock = xsocket(ai->ai_family, SOCK_DGRAM,
+ (ai->ai_family == AF_INET) ? IPPROTO_ICMP : IPPROTO_ICMPV6);
+ if (TT.I && bind(TT.sock, sa, sizeof(src_addr))) perror_exit("bind");
+
+ if (TT.t) {
+ len = TT.t;
+
+ if (ai->ai_family == AF_INET)
+ setsockopt(TT.sock, IPPROTO_IP, IP_TTL, &len, 4);
+ else setsockopt(TT.sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &len, 4);
+ }
+
+ if (!(toys.optflags&FLAG_q)) {
+ printf("Ping %s (%s)", *toys.optargs, ntop(ai->ai_addr));
+ if (TT.I) {
+ *toybuf = 0;
+ printf(" from %s (%s)", TT.I, ntop(sa));
+ }
+ // 20 byte TCP header, 8 byte ICMP header, plus data payload
+ printf(": %ld(%ld) bytes.\n", TT.s, TT.s+28);
+ }
+ toys.exitval = 1;
+
+ tW = tw = 0;
+ tnext = millitime();
+ if (TT.w) tw = TT.w*1000+tnext;
+
+ // Send/receive packets
+ for (;;) {
+ int waitms = INT_MAX;
+
+ // Exit due to timeout? (TODO: timeout is after last packet, waiting if
+ // any packets ever dropped. Not timeout since packet was dropped.)
+ tnow = millitime();
+ if (tW) if (0>=(waitms = tW-tnow) || !sent) break;
+ if (tw) {
+ if (tnow>tw) break;
+ else if (waitms>tw-tnow) waitms = tw-tnow;
+ // Time to send the next packet?
+ } else if (tnext-tnow <= 0) {
+ tnext += TT.i_ms;
+
+ memset(ih, 0, sizeof(*ih));
+ ih->type = (ai->ai_family == AF_INET) ? 8 : 128;
+ ih->un.echo.id = getpid();
+ ih->un.echo.sequence = ++seq;
+ if (TT.s >= 4) *(unsigned *)(ih+1) = tnow;
+
+ ih->checksum = 0;
+ ih->checksum = pingchksum((void *)toybuf, TT.s+sizeof(*ih));
+ xsendto(TT.sock, toybuf, TT.s+sizeof(*ih), ai->ai_addr);
+ sent++;
+ if (toys.optflags&FLAG_f) printf(".");
+
+ // last packet?
+ if (TT.c) if (!--TT.c) {
+ if (!TT.W) break;
+ tW = tnow + TT.W*1000;
+ }
+ }
+
+ // This is down here so it's against new period if we just sent a packet
+ if (!tw && waitms>tnext-tnow) waitms = tnext-tnow;
+
+ // wait for next packet or timeout
+
+ if (waitms<0) waitms = 0;
+ pfd.fd = TT.sock;
+ pfd.events = POLLIN;
+ if (0>(len = poll(&pfd, 1, waitms))) break;
+ if (!len) continue;
+
+ len = sizeof(src_addr2);
+ len = recvfrom(TT.sock, toybuf, sizeof(toybuf), 0, sa2, (void *)&len);
+ sent--;
+
+ // reply id == 0 for ipv4, 129 for ipv6
+
+ if (!(toys.optflags&FLAG_q)) {
+ printf("%d bytes from %s: icmp_seq=%d ttl=%d", len, ntop(sa2),
+ ih->un.echo.sequence, 0);
+ if (len >= sizeof(*ih)+4) {
+ unsigned lunchtime = millitime()-*(unsigned *)(ih+1);
+
+ printf(" time=%u.%03u", lunchtime/1000, lunchtime%1000);
+ }
+ xputc('\n');
+ }
+
+ toys.exitval = 0;
+ }
if (CFG_TOYBOX_FREE) {
freeaddrinfo(ai2);
diff --git a/toys/posix/cksum.c b/toys/posix/cksum.c
index bcb2843d..ee7c6f54 100644
--- a/toys/posix/cksum.c
+++ b/toys/posix/cksum.c
@@ -5,6 +5,7 @@
* See http://opengroup.org/onlinepubs/9699919799/utilities/cksum.html
USE_CKSUM(NEWTOY(cksum, "HIPLN", TOYFLAG_BIN))
+USE_CRC32(NEWTOY(crc32, 0, TOYFLAG_BIN))
config CKSUM
bool "cksum"
@@ -19,10 +20,19 @@ config CKSUM
-L Little endian (defaults to big endian)
-P Pre-inversion
-I Skip post-inversion
- -N Do not include length in CRC calculation
+ -N Do not include length in CRC calculation (or output)
+
+config CRC32
+ bool "crc32"
+ default y
+ help
+ usage: crc32 [file...]
+
+ Output crc32 checksum for each file.
*/
#define FOR_cksum
+#define FORCE_FLAGS
#include "toys.h"
GLOBALS(
@@ -44,13 +54,12 @@ static void do_cksum(int fd, char *name)
unsigned crc = (toys.optflags & FLAG_P) ? 0xffffffff : 0;
uint64_t llen = 0, llen2;
unsigned (*cksum)(unsigned crc, unsigned char c);
+ int len, i;
cksum = (toys.optflags & FLAG_L) ? cksum_le : cksum_be;
// CRC the data
for (;;) {
- int len, i;
-
len = read(fd, toybuf, sizeof(toybuf));
if (len<0) perror_msg_raw(name);
if (len<1) break;
@@ -69,10 +78,10 @@ static void do_cksum(int fd, char *name)
}
}
- printf((toys.optflags & FLAG_H) ? "%x" : "%u",
+ printf((toys.optflags & FLAG_H) ? "%08x" : "%u",
(toys.optflags & FLAG_I) ? crc : ~crc);
- printf(" %"PRIu64, llen2);
- if (strcmp("-", name)) printf(" %s", name);
+ if (!(toys.optflags&FLAG_N)) printf(" %"PRIu64, llen2);
+ if (toys.optc) printf(" %s", name);
xputc('\n');
}
@@ -81,3 +90,10 @@ void cksum_main(void)
crc_init(TT.crc_table, toys.optflags & FLAG_L);
loopfiles(toys.optargs, do_cksum);
}
+
+void crc32_main(void)
+{
+ toys.optflags |= FLAG_H|FLAG_N|FLAG_P|FLAG_L;
+ if (toys.optc) toys.optc--;
+ cksum_main();
+}
diff --git a/toys/posix/ps.c b/toys/posix/ps.c
index fd9b54bc..8ee68ad6 100644
--- a/toys/posix/ps.c
+++ b/toys/posix/ps.c
@@ -1417,7 +1417,7 @@ static void top_common(
mix.count = 0;
while (old.count || new.count) {
- struct carveup *otb = *old.tb, *ntb = *new.tb;
+ struct carveup *otb = old.tb ? *old.tb : 0, *ntb = new.tb ? *new.tb : 0;
// If we just have old for this process, it exited. Discard it.
if (old.count && (!new.count || *otb->slot < *ntb->slot)) {