git: 149466a516b2 - stable/13 - ping: split the visual part of -f into a new option -.

From: Piotr Pawel Stefaniak <pstef_at_FreeBSD.org>
Date: Sat, 24 Dec 2022 07:22:34 UTC
The branch stable/13 has been updated by pstef:

URL: https://cgit.FreeBSD.org/src/commit/?id=149466a516b2561947f7b4e83807b9efa57e9915

commit 149466a516b2561947f7b4e83807b9efa57e9915
Author:     Piotr Pawel Stefaniak <pstef@FreeBSD.org>
AuthorDate: 2022-04-11 14:58:24 +0000
Commit:     Piotr Pawel Stefaniak <pstef@FreeBSD.org>
CommitDate: 2022-12-24 06:50:04 +0000

    ping: split the visual part of -f into a new option -.
    
    Differential Revision:  https://reviews.freebsd.org/D34882
    
    (cherry picked from commit d399eb3ef7f8a8189b73d179e07119b30127efb9)
---
 sbin/ping/main.h  |  4 ++--
 sbin/ping/ping.8  | 29 ++++++++++++++++++++++++-----
 sbin/ping/ping.c  | 23 +++++++++++++++++------
 sbin/ping/ping6.c | 21 ++++++++++++++++-----
 4 files changed, 59 insertions(+), 18 deletions(-)

diff --git a/sbin/ping/main.h b/sbin/ping/main.h
index 0f987e9a20ae..51a368403bab 100644
--- a/sbin/ping/main.h
+++ b/sbin/ping/main.h
@@ -40,7 +40,7 @@
 #else
  #define PING4ADDOPTS
 #endif
-#define PING4OPTS "4AaC:c:DdfG:g:Hh:I:i:Ll:M:m:nop:QqRrS:s:T:t:vW:z:" PING4ADDOPTS
+#define PING4OPTS ".::4AaC:c:DdfG:g:Hh:I:i:Ll:M:m:nop:QqRrS:s:T:t:vW:z:" PING4ADDOPTS
 
 #if defined(INET6) && defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
  #define PING6ADDOPTS "P:"
@@ -49,7 +49,7 @@
 #else
  #define PING6ADDOPTS
 #endif
-#define PING6OPTS "6Aab:C:c:Dde:fHI:i:k:l:m:nNoOp:qS:s:t:uvyYW:z:" PING6ADDOPTS
+#define PING6OPTS ".::6Aab:C:c:Dde:fHI:i:k:l:m:nNoOp:qS:s:t:uvyYW:z:" PING6ADDOPTS
 
 void usage(void) __dead2;
 
diff --git a/sbin/ping/ping.8 b/sbin/ping/ping.8
index 6048bbc6b749..fceff650fbc1 100644
--- a/sbin/ping/ping.8
+++ b/sbin/ping/ping.8
@@ -41,6 +41,7 @@ packets to network hosts
 .Sh SYNOPSIS
 .Nm
 .Op Fl 4AaDdfHnoQqRrv
+.Op Fl .\& Ns Ar chars
 .Op Fl C Ar pcp
 .Op Fl c Ar count
 .Op Fl G Ar sweepmaxsize
@@ -60,6 +61,7 @@ packets to network hosts
 .Ar IPv4-host
 .Nm
 .Op Fl 4AaDdfHLnoQqRrv
+.Op Fl .\& Ns Ar chars
 .Op Fl C Ar pcp
 .Op Fl c Ar count
 .Op Fl I Ar iface
@@ -78,6 +80,7 @@ packets to network hosts
 .Ar IPv4-mcast-group
 .Nm
 .Op Fl 6AaDdEfHNnOoquvYyZ
+.Op Fl .\& Ns Ar chars
 .Op Fl b Ar bufsiz
 .Op Fl c Ar count
 .Op Fl e Ar gateway
@@ -145,6 +148,22 @@ as
 .Nm ping6 .
 .Ss Options common to both IPv4 and IPv6 targets
 .Bl -tag -width indent
+.It Fl .\& Ns Ar chars
+By default, for every
+.Tn ECHO_REQUEST
+sent, a period
+.Dq .\&
+is printed, while for every
+.Tn ECHO_REPLY
+received, a backspace is printed.
+This option takes an optional string argument listing characters
+that will be printed one by one in the provided order
+instead of the default period.
+.Pp
+Example usage:
+.Bd -literal -offset indent
+ping -.0123456789 freebsd.org
+.Ed
 .It Fl A
 Audible.
 Output a bell
@@ -188,13 +207,13 @@ option on the socket being used.
 Flood ping.
 Outputs packets as fast as they come back or one hundred times per second,
 whichever is more.
-For every
+Implies
+.Fl .\&
+to print a period for every
 .Tn ECHO_REQUEST
-sent a period
-.Dq .\&
-is printed, while for every
+sent and a backspace for every
 .Tn ECHO_REPLY
-received a backspace is printed.
+received.
 This provides a rapid display of how many packets are being dropped.
 Only the super-user may use this option.
 .Bf -emphasis
diff --git a/sbin/ping/ping.c b/sbin/ping/ping.c
index 00ac8eadddff..6956b9a68ad2 100644
--- a/sbin/ping/ping.c
+++ b/sbin/ping/ping.c
@@ -158,6 +158,7 @@ static int options;
 #define	F_SWEEP		0x200000
 #define	F_WAITTIME	0x400000
 #define	F_IP_VLAN_PCP	0x800000
+#define	F_DOT		0x1000000
 
 /*
  * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
@@ -176,7 +177,9 @@ static int srecv;		/* receive socket file descriptor */
 static u_char outpackhdr[IP_MAXPACKET], *outpack;
 static char BBELL = '\a';	/* characters written for MISSED and AUDIBLE */
 static char BSPACE = '\b';	/* characters written for flood */
-static char DOT = '.';
+static const char *DOT = ".";
+static size_t DOTlen = 1;
+static size_t DOTidx = 0;
 static char *hostname;
 static char *shostname;
 static int ident;		/* process id to identify our packets */
@@ -303,6 +306,13 @@ ping(int argc, char *const *argv)
 	outpack = outpackhdr + sizeof(struct ip);
 	while ((ch = getopt(argc, argv, PING4OPTS)) != -1) {
 		switch(ch) {
+		case '.':
+			options |= F_DOT;
+			if (optarg != NULL) {
+				DOT = optarg;
+				DOTlen = strlen(optarg);
+			}
+			break;
 		case '4':
 			/* This option is processed in main(). */
 			break;
@@ -340,6 +350,7 @@ ping(int argc, char *const *argv)
 				err(EX_NOPERM, "-f flag");
 			}
 			options |= F_FLOOD;
+			options |= F_DOT;
 			setbuf(stdout, (char *)NULL);
 			break;
 		case 'G': /* Maximum packet size for ping sweep */
@@ -1117,8 +1128,8 @@ pinger(void)
 	}
 	ntransmitted++;
 	sntransmitted++;
-	if (!(options & F_QUIET) && options & F_FLOOD)
-		(void)write(STDOUT_FILENO, &DOT, 1);
+	if (!(options & F_QUIET) && options & F_DOT)
+		(void)write(STDOUT_FILENO, &DOT[DOTidx++ % DOTlen], 1);
 }
 
 /*
@@ -1238,7 +1249,7 @@ pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)
 			return;
 		}
 
-		if (options & F_FLOOD)
+		if (options & F_DOT)
 			(void)write(STDOUT_FILENO, &BSPACE, 1);
 		else {
 			(void)printf("%zd bytes from %s: icmp_seq=%u", cc,
@@ -1412,7 +1423,7 @@ pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)
 			}
 			if (i == old_rrlen
 			    && !bcmp((char *)cp, old_rr, i)
-			    && !(options & F_FLOOD)) {
+			    && !(options & F_DOT)) {
 				(void)printf("\t(same route)");
 				hlen -= i;
 				cp += i;
@@ -1447,7 +1458,7 @@ pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)
 			(void)printf("\nunknown option %x", *cp);
 			break;
 		}
-	if (!(options & F_FLOOD)) {
+	if (!(options & F_DOT)) {
 		(void)putchar('\n');
 		(void)fflush(stdout);
 	}
diff --git a/sbin/ping/ping6.c b/sbin/ping/ping6.c
index b17d5805eed5..74d36f0357f8 100644
--- a/sbin/ping/ping6.c
+++ b/sbin/ping/ping6.c
@@ -201,6 +201,7 @@ struct tv32 {
 #define F_DONTFRAG	0x1000000
 #define F_NOUSERDATA	(F_NODEADDR | F_FQDN | F_FQDNOLD | F_SUPTYPES)
 #define	F_WAITTIME	0x2000000
+#define	F_DOT		0x4000000
 static u_int options;
 
 #define IN6LEN		sizeof(struct in6_addr)
@@ -227,7 +228,9 @@ static int srecv;		/* receive socket file descriptor */
 static u_char outpack[MAXPACKETLEN];
 static char BSPACE = '\b';	/* characters written for flood */
 static char BBELL = '\a';	/* characters written for AUDIBLE */
-static char DOT = '.';
+static const char *DOT = ".";
+static size_t DOTlen = 1;
+static size_t DOTidx = 0;
 static char *hostname;
 static int ident;		/* process id to identify our packets */
 static u_int8_t nonce[8];	/* nonce field for node information */
@@ -352,6 +355,13 @@ ping6(int argc, char *argv[])
 
 	while ((ch = getopt(argc, argv, PING6OPTS)) != -1) {
 		switch (ch) {
+		case '.':
+			options |= F_DOT;
+			if (optarg != NULL) {
+				DOT = optarg;
+				DOTlen = strlen(optarg);
+			}
+			break;
 		case '6':
 			/* This option is processed in main(). */
 			break;
@@ -437,6 +447,7 @@ ping6(int argc, char *argv[])
 				errx(1, "Must be superuser to flood ping");
 			}
 			options |= F_FLOOD;
+			options |= F_DOT;
 			setbuf(stdout, (char *)NULL);
 			break;
 		case 'e':
@@ -1463,8 +1474,8 @@ pinger(void)
 		(void)printf("ping6: wrote %s %d chars, ret=%d\n",
 		    hostname, cc, i);
 	}
-	if (!(options & F_QUIET) && options & F_FLOOD)
-		(void)write(STDOUT_FILENO, &DOT, 1);
+	if (!(options & F_QUIET) && options & F_DOT)
+		(void)write(STDOUT_FILENO, &DOT[DOTidx++ % DOTlen], 1);
 
 	return(0);
 }
@@ -1661,7 +1672,7 @@ pr_pack(u_char *buf, int cc, struct msghdr *mhdr)
 			return;
 		}
 
-		if (options & F_FLOOD)
+		if (options & F_DOT)
 			(void)write(STDOUT_FILENO, &BSPACE, 1);
 		else {
 			if (options & F_AUDIBLE)
@@ -1853,7 +1864,7 @@ pr_pack(u_char *buf, int cc, struct msghdr *mhdr)
 		pr_icmph(icp, end);
 	}
 
-	if (!(options & F_FLOOD)) {
+	if (!(options & F_DOT)) {
 		(void)putchar('\n');
 		if (options & F_VERBOSE)
 			pr_exthdrs(mhdr);