aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2018-02-11 08:21:55 (GMT)
committerandroid-build-team Robot <android-build-team-robot@google.com>2018-02-11 08:21:55 (GMT)
commit982ca94ba622f71ceb819db646c973a97ed4c26f (patch)
tree1d7334adfaeb60c3a5f447fe2fdedc41cd906066
parent81d45d5033ac18cc630a3e6199df791bb6a8ead6 (diff)
parent1c98a8e1fb384161159b5ebc5550503818bb255f (diff)
downloadandroid_external_toybox-982ca94ba622f71ceb819db646c973a97ed4c26f.zip
android_external_toybox-982ca94ba622f71ceb819db646c973a97ed4c26f.tar.gz
android_external_toybox-982ca94ba622f71ceb819db646c973a97ed4c26f.tar.bz2
Snap for 4598635 from 1c98a8e1fb384161159b5ebc5550503818bb255f to pi-release
Change-Id: Ibd420c4cdde9c98376038207c572c144c1368060
-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.c18
-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.c3
13 files changed, 274 insertions, 83 deletions
diff --git a/.config b/.config
index 22616a4..d0de7b0 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 a7a427f..14c9c65 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 8f4f113..79da5e6 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 e0c24f3..7e2ba20 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 c5ddadd..6f01070 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 f648b83..d38c4d2 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 6743a3b..0c7fbb3 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.c b/lib/lib.c
index 7f5fbbd..e5c9479 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -1036,13 +1036,13 @@ void names_to_pid(char **names, int (*callback)(pid_t pid, char *name))
for (cur = names; *cur; cur++) {
struct stat st1, st2;
- char *bb = basename(*cur);
- off_t len;
+ char *bb = getbasename(*cur);
+ off_t len = strlen(bb);
- // fast path: only matching a filename (no path) that fits in comm
- if (strncmp(comm, bb, 15)) continue;
- len = strlen(bb);
- if (bb==*cur && len<16) goto match;
+ // Fast path: only matching a filename (no path) that fits in comm.
+ // `len` must be 14 or less because with a full 15 bytes we don't
+ // know whether the name fit or was truncated.
+ if (len<=14 && bb==*cur && !strcmp(comm, bb)) goto match;
// If we have a path to existing file only match if same inode
if (bb!=*cur && !stat(*cur, &st1)) {
@@ -1059,12 +1059,12 @@ void names_to_pid(char **names, int (*callback)(pid_t pid, char *name))
sprintf(cmd = libbuf+16, "/proc/%u/cmdline", u);
len = sizeof(libbuf)-17;
if (!(cmd = readfileat(AT_FDCWD, cmd, cmd, &len))) continue;
- // readfile only guarnatees one null terminator and we need two
+ // readfile only guarantees one null terminator and we need two
// (yes the kernel should do this for us, don't care)
cmd[len] = 0;
}
- if (!strcmp(bb, basename(cmd))) goto match;
- if (bb!=*cur && !strcmp(bb, basename(cmd+strlen(cmd)+1))) goto match;
+ if (!strcmp(bb, getbasename(cmd))) goto match;
+ if (bb!=*cur && !strcmp(bb, getbasename(cmd+strlen(cmd)+1))) goto match;
continue;
match:
if (callback(u, *cur)) break;
diff --git a/lib/lib.h b/lib/lib.h
index 9466298..939d612 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 5c6d4f7..846be31 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 545ad79..3802918 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 bcb2843..ee7c6f5 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 fd9b54b..e94902b 100644
--- a/toys/posix/ps.c
+++ b/toys/posix/ps.c
@@ -1417,7 +1417,8 @@ static void top_common(
mix.count = 0;
while (old.count || new.count) {
- struct carveup *otb = *old.tb, *ntb = *new.tb;
+ struct carveup *otb = old.count ? *old.tb : 0,
+ *ntb = new.count ? *new.tb : 0;
// If we just have old for this process, it exited. Discard it.
if (old.count && (!new.count || *otb->slot < *ntb->slot)) {