schweikert / fping

High performance ping tool

Home Page:https://fping.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

-D, --timestamp with custom time string eq: %Y-%m-%d %H:%M:%S

coolshou opened this issue · comments

Currently the --timestamp output string as following, can we custom it in human readable format eq: %Y-%m-%d %H:%M:%S
fping -D -l 192.168.0.21
[1711612145.46829] 192.168.0.21 : [0], 64 bytes, 27.2 ms (27.2 avg, 0% loss)
[1711612146.48808] 192.168.0.21 : [1], 64 bytes, 46.0 ms (36.6 avg, 0% loss)
[1711612147.46816] 192.168.0.21 : [2], 64 bytes, 26.1 ms (33.1 avg, 0% loss)

We can't change the format, so this would mean adding yet another option (and in general we have too many already). We could possibly add --timestamp-format (without a short-option equivalent), if somebody wants to create a pull request for that.

If I see this correctly, the one function in optparse.c would first have to be created or extended so that the long name of the comman line option can be used without short.
Currently the short is always returned as ASCII int.

I did a quick test, a number greater than 255 can be used instead of a character for options that only have a long name:

diff --git a/src/fping.c b/src/fping.c
index c58e20c..f7a3129 100644
--- a/src/fping.c
+++ b/src/fping.c
@@ -552,6 +552,7 @@ int main(int argc, char **argv)
         { "version", 'v', OPTPARSE_NONE },
         { "reachable", 'x', OPTPARSE_REQUIRED },
         { "fast-reachable", 'X', OPTPARSE_REQUIRED },
+        { "long-only-test", 256, OPTPARSE_NONE },
 #if defined(DEBUG) || defined(_DEBUG)
         { NULL, 'z', OPTPARSE_REQUIRED },
 #endif
@@ -872,6 +873,11 @@ int main(int argc, char **argv)
             outage_flag = 1;
             break;
 
+        case 256:
+            puts("long-only option given");
+            exit(0);
+            break;
+
         case '?':
             fprintf(stderr, "%s: %s\n", argv[0], optparse_state.errmsg);
             fprintf(stderr, "see 'fping -h' for usage information\n");

This works as intended for the long option:

$ ./src/fping --long-only-test
long-only option given

#defines or an enum could be used instead of simple numbers.

I do not know if this is the way optparse_long() is intended to be used for options without a short (i.e., one character) name, but it seems to work.

My quick solution goes in a similar direction. I use the ASCII number 0 and then look at which long-option is set exactly.
I don't know yet whether this is well thought out. But it seems to work for now.

diff --git a/src/fping.c b/src/fping.c
index c58e20c..9177f00 100644
--- a/src/fping.c
+++ b/src/fping.c
@@ -357,6 +357,7 @@ int per_recv_flag, report_all_rtts_flag, name_flag, addr_flag, backoff_flag, rdn
 int multif_flag, timeout_flag, fast_reachable;
 int outage_flag = 0;
 int timestamp_flag = 0;
+int timestamp_format_flag = 0;
 int random_data_flag = 0;
 int cumulative_stats_flag = 0;
 #if defined(DEBUG) || defined(_DEBUG)
@@ -522,6 +523,7 @@ int main(int argc, char **argv)
         { "vcount", 'C', OPTPARSE_REQUIRED },
         { "rdns", 'd', OPTPARSE_NONE },
         { "timestamp", 'D', OPTPARSE_NONE },
+        { "timestamp-format", '0', OPTPARSE_NONE },
         { "elapsed", 'e', OPTPARSE_NONE },
         { "file", 'f', OPTPARSE_REQUIRED },
         { "generate", 'g', OPTPARSE_NONE },
@@ -561,6 +563,13 @@ int main(int argc, char **argv)
     float opt_value_float;
     while ((c = optparse_long(&optparse_state, longopts, NULL)) != EOF) {
         switch (c) {
+        case '0':
+              if(strstr(optparse_state.optlongname, "timestamp-format") != NULL) {
+                timestamp_format_flag = 1;
+                puts("timestamp-format found");
+                exit(0);
+              }
+            break;
         case '4':
 #ifdef IPV6
             if (hints_ai_family != AF_UNSPEC && hints_ai_family != AF_INET) {
diff --git a/src/optparse.c b/src/optparse.c
index 4242bff..63a9f40 100644
--- a/src/optparse.c
+++ b/src/optparse.c
@@ -238,12 +238,14 @@ optparse_long(struct optparse *options,
     /* Parse as long option. */
     options->errmsg[0] = '\0';
     options->optopt = 0;
+    options->optlongname = 0;
     options->optarg = 0;
     option += 2; /* skip "--" */
     options->optind++;
     for (int i = 0; !longopts_end(longopts, i); i++) {
         const char *name = longopts[i].longname;
         if (longopts_match(name, option)) {
+            options->optlongname = option;
             if (longindex)
                 *longindex = i;
             options->optopt = longopts[i].shortname;
diff --git a/src/optparse.h b/src/optparse.h
index f124b75..7a555ed 100644
--- a/src/optparse.h
+++ b/src/optparse.h
@@ -48,6 +48,7 @@ struct optparse {
     int permute;
     int optind;
     int optopt;
+    char *optlongname;
     char *optarg;
     char errmsg[64];
     int subopt;

Later in the execution, you must of course check whether "timestamp_flag = 1" and "timestamp_format_flag = 1", because the longoption can also be set without -D.

Here is my first working solution. I'm not happy with this solution, but it works
develop...gsnw:fping:issue/310

I understand the original request to allow specifying a format string, similar to what is possible with date. I do not like the additional attack surface created by allowing arbitrary format strings as user input, but would instead prefer to provide a few keywords with which to select a non-default format. One example of this can be seen in dmesg:

$ dmesg --help | section -- --time-format
     --time-format <format>  show timestamp using the given format:
                               [delta|reltime|ctime|notime|iso]

There, ctime selects what is also called human readable time,

[Mon May 27 15:45:41 2024] …

while iso selects a format compatible with ISO-8601:

2024-05-27T15:45:41,280072+02:00 …

@schweikert: What do you think?

In my opinion, this is quite a good idea, instead of a free format input, which requires a complicated input check.
I have already made preparations for the proposal in my new version and created a function print_timestamp_format().

Link in previous post from me

Just created pull request #321

When some one need a update or other formats, please create a new issue or pull request