The attached addresses the case when the user passes an invalid
long option to a utility which does not have any long options
(apart from --help/--version, of course).
See commit comment for details.

I saw this when trying to write the check to verify the options
mentioned by usage() versus that actually recognized by getopt_long.

I'm also a bit confused that/why we obviously cannot teach gnulib's
parse_long_options to already diagnose this in the first run, so
that the following getopt_long call would become obsolete?

BTW: How do we mark patches which belong to several tools and
are user-visible, but the list of utilities is quite long?
  cksum dd hostid hostname link logname nohup sleep tsort
  unlink uptime users whoami yes
Probably this warrants a NEW entry?

Comments welcome.

Thanks & have a nice day,
Berny
>From 19f7f64aacbb184fdee948a0847ea06d4d9836ae Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <[email protected]>
Date: Tue, 28 Nov 2017 17:32:29 +0100
Subject: [PATCH] maint: fix output for unknown long options for utils without
 long option

Previously, e.g. cksum failed to output the offending unknown long
option:
  $ cksum --unknown-opt
  cksum: invalid option -- '-'
  Try 'cksum --help' for more information.
i.e., it tried to diagnose '-' as short option.
Instead, it should diagnose the unknown long option:
  $ cksum --unknown-opt
  cksum: unrecognized option '--unknown-opt'
  Try 'cksum --help' for more information.

* src/cksum.c (long_options): Add struct with null entry only.
(main): Use it in the getopt_long call.
* src/dd.c: Likewise.
* src/hostid.c: Likewise.
* src/hostname.c: Likewise.
* src/link.c: Likewise.
* src/logname.c: Likewise.
* src/nohup.c: Likewise.
* src/sleep.c: Likewise.
* src/tsort.c: Likewise.
* src/unlink.c: Likewise.
* src/uptime.c: Likewise.
* src/users.c: Likewise.
* src/whoami.c: Likewise.
* src/yes.c: Likewise.
---
 src/cksum.c    | 7 ++++++-
 src/dd.c       | 7 ++++++-
 src/hostid.c   | 7 ++++++-
 src/hostname.c | 7 ++++++-
 src/link.c     | 7 ++++++-
 src/logname.c  | 7 ++++++-
 src/nohup.c    | 7 ++++++-
 src/sleep.c    | 7 ++++++-
 src/tsort.c    | 7 ++++++-
 src/unlink.c   | 7 ++++++-
 src/uptime.c   | 7 ++++++-
 src/users.c    | 7 ++++++-
 src/whoami.c   | 7 ++++++-
 src/yes.c      | 7 ++++++-
 14 files changed, 84 insertions(+), 14 deletions(-)

diff --git a/src/cksum.c b/src/cksum.c
index 0877ce519..deceb4dd4 100644
--- a/src/cksum.c
+++ b/src/cksum.c
@@ -107,6 +107,11 @@ main (void)
 # include "die.h"
 # include "error.h"
 
+static struct option const long_options[] =
+{
+  {NULL, 0, NULL, 0}
+};
+
 /* Number of bytes to read at once.  */
 # define BUFLEN (1 << 16)
 
@@ -291,7 +296,7 @@ main (int argc, char **argv)
 
   parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE, Version,
                       usage, AUTHORS, (char const *) NULL);
-  if (getopt_long (argc, argv, "", NULL, NULL) != -1)
+  if (getopt_long (argc, argv, "", long_options, NULL) != -1)
     usage (EXIT_FAILURE);
 
   have_read_stdin = false;
diff --git a/src/dd.c b/src/dd.c
index 0ff618c96..7b3d2fd37 100644
--- a/src/dd.c
+++ b/src/dd.c
@@ -46,6 +46,11 @@
   proper_name ("David MacKenzie"), \
   proper_name ("Stuart Kemp")
 
+static struct option const long_options[] =
+{
+  {NULL, 0, NULL, 0}
+};
+
 /* Use SA_NOCLDSTOP as a proxy for whether the sigaction machinery is
    present.  */
 #ifndef SA_NOCLDSTOP
@@ -2394,7 +2399,7 @@ main (int argc, char **argv)
                       usage, AUTHORS, (char const *) NULL);
   close_stdout_required = false;
 
-  if (getopt_long (argc, argv, "", NULL, NULL) != -1)
+  if (getopt_long (argc, argv, "", long_options, NULL) != -1)
     usage (EXIT_FAILURE);
 
   /* Initialize translation table to identity translation. */
diff --git a/src/hostid.c b/src/hostid.c
index 8766edac3..c676bdcd8 100644
--- a/src/hostid.c
+++ b/src/hostid.c
@@ -32,6 +32,11 @@
 
 #define AUTHORS proper_name ("Jim Meyering")
 
+static struct option const long_options[] =
+{
+  {NULL, 0, NULL, 0}
+};
+
 void
 usage (int status)
 {
@@ -66,7 +71,7 @@ main (int argc, char **argv)
 
   parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,
                       usage, AUTHORS, (char const *) NULL);
-  if (getopt_long (argc, argv, "", NULL, NULL) != -1)
+  if (getopt_long (argc, argv, "", long_options, NULL) != -1)
     usage (EXIT_FAILURE);
 
   if (optind < argc)
diff --git a/src/hostname.c b/src/hostname.c
index 0a57cb409..560eb7f43 100644
--- a/src/hostname.c
+++ b/src/hostname.c
@@ -33,6 +33,11 @@
 
 #define AUTHORS proper_name ("Jim Meyering")
 
+static struct option const long_options[] =
+{
+  {NULL, 0, NULL, 0}
+};
+
 #if !defined HAVE_SETHOSTNAME && defined HAVE_SYSINFO && \
      defined HAVE_SYS_SYSTEMINFO_H
 # include <sys/systeminfo.h>
@@ -83,7 +88,7 @@ main (int argc, char **argv)
 
   parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,
                       usage, AUTHORS, (char const *) NULL);
-  if (getopt_long (argc, argv, "", NULL, NULL) != -1)
+  if (getopt_long (argc, argv, "", long_options, NULL) != -1)
     usage (EXIT_FAILURE);
 
   if (argc == optind + 1)
diff --git a/src/link.c b/src/link.c
index 89711c1fd..3b9c776c1 100644
--- a/src/link.c
+++ b/src/link.c
@@ -36,6 +36,11 @@
 
 #define AUTHORS proper_name ("Michael Stone")
 
+static struct option const long_options[] =
+{
+  {NULL, 0, NULL, 0}
+};
+
 void
 usage (int status)
 {
@@ -69,7 +74,7 @@ main (int argc, char **argv)
 
   parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,
                       usage, AUTHORS, (char const *) NULL);
-  if (getopt_long (argc, argv, "", NULL, NULL) != -1)
+  if (getopt_long (argc, argv, "", long_options, NULL) != -1)
     usage (EXIT_FAILURE);
 
   if (argc < optind + 2)
diff --git a/src/logname.c b/src/logname.c
index 3529559ef..db5836590 100644
--- a/src/logname.c
+++ b/src/logname.c
@@ -30,6 +30,11 @@
 
 #define AUTHORS proper_name ("FIXME: unknown")
 
+static struct option const long_options[] =
+{
+  {NULL, 0, NULL, 0}
+};
+
 void
 usage (int status)
 {
@@ -64,7 +69,7 @@ main (int argc, char **argv)
 
   parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,
                       usage, AUTHORS, (char const *) NULL);
-  if (getopt_long (argc, argv, "", NULL, NULL) != -1)
+  if (getopt_long (argc, argv, "", long_options, NULL) != -1)
     usage (EXIT_FAILURE);
 
   if (optind < argc)
diff --git a/src/nohup.c b/src/nohup.c
index 162e7cd50..7bf32d24a 100644
--- a/src/nohup.c
+++ b/src/nohup.c
@@ -34,6 +34,11 @@
 
 #define AUTHORS proper_name ("Jim Meyering")
 
+static struct option const long_options[] =
+{
+  {NULL, 0, NULL, 0}
+};
+
 /* Exit statuses.  */
 enum
   {
@@ -101,7 +106,7 @@ main (int argc, char **argv)
 
   parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,
                       usage, AUTHORS, (char const *) NULL);
-  if (getopt_long (argc, argv, "+", NULL, NULL) != -1)
+  if (getopt_long (argc, argv, "+", long_options, NULL) != -1)
     usage (exit_internal_failure);
 
   if (argc <= optind)
diff --git a/src/sleep.c b/src/sleep.c
index de09ff358..889719f01 100644
--- a/src/sleep.c
+++ b/src/sleep.c
@@ -35,6 +35,11 @@
   proper_name ("Jim Meyering"), \
   proper_name ("Paul Eggert")
 
+static struct option const long_options[] =
+{
+  {NULL, 0, NULL, 0}
+};
+
 void
 usage (int status)
 {
@@ -111,7 +116,7 @@ main (int argc, char **argv)
 
   parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,
                       usage, AUTHORS, (char const *) NULL);
-  if (getopt_long (argc, argv, "", NULL, NULL) != -1)
+  if (getopt_long (argc, argv, "", long_options, NULL) != -1)
     usage (EXIT_FAILURE);
 
   if (argc == 1)
diff --git a/src/tsort.c b/src/tsort.c
index 73a876c38..cb84393e9 100644
--- a/src/tsort.c
+++ b/src/tsort.c
@@ -40,6 +40,11 @@
 
 #define AUTHORS proper_name ("Mark Kettenis")
 
+static struct option const long_options[] =
+{
+  {NULL, 0, NULL, 0}
+};
+
 /* Token delimiters when reading from a file.  */
 #define DELIM " \t\n"
 
@@ -553,7 +558,7 @@ main (int argc, char **argv)
 
   parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE, Version,
                       usage, AUTHORS, (char const *) NULL);
-  if (getopt_long (argc, argv, "", NULL, NULL) != -1)
+  if (getopt_long (argc, argv, "", long_options, NULL) != -1)
     usage (EXIT_FAILURE);
 
   if (1 < argc - optind)
diff --git a/src/unlink.c b/src/unlink.c
index 3d8bb0bfd..f173d323e 100644
--- a/src/unlink.c
+++ b/src/unlink.c
@@ -36,6 +36,11 @@
 
 #define AUTHORS proper_name ("Michael Stone")
 
+static struct option const long_options[] =
+{
+  {NULL, 0, NULL, 0}
+};
+
 void
 usage (int status)
 {
@@ -68,7 +73,7 @@ main (int argc, char **argv)
 
   parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,
                       usage, AUTHORS, (char const *) NULL);
-  if (getopt_long (argc, argv, "", NULL, NULL) != -1)
+  if (getopt_long (argc, argv, "", long_options, NULL) != -1)
     usage (EXIT_FAILURE);
 
   if (argc < optind + 1)
diff --git a/src/uptime.c b/src/uptime.c
index cafcda204..d1951d50f 100644
--- a/src/uptime.c
+++ b/src/uptime.c
@@ -47,6 +47,11 @@
   proper_name ("David MacKenzie"), \
   proper_name ("Kaveh Ghazi")
 
+static struct option const long_options[] =
+{
+  {NULL, 0, NULL, 0}
+};
+
 static void
 print_uptime (size_t n, const STRUCT_UTMP *this)
 {
@@ -236,7 +241,7 @@ main (int argc, char **argv)
 
   parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,
                       usage, AUTHORS, (char const *) NULL);
-  if (getopt_long (argc, argv, "", NULL, NULL) != -1)
+  if (getopt_long (argc, argv, "", long_options, NULL) != -1)
     usage (EXIT_FAILURE);
 
   switch (argc - optind)
diff --git a/src/users.c b/src/users.c
index 7b1d8cdba..4bdebff44 100644
--- a/src/users.c
+++ b/src/users.c
@@ -36,6 +36,11 @@
   proper_name ("Joseph Arceneaux"), \
   proper_name ("David MacKenzie")
 
+static struct option const long_options[] =
+{
+  {NULL, 0, NULL, 0}
+};
+
 static int
 userid_compare (const void *v_a, const void *v_b)
 {
@@ -130,7 +135,7 @@ main (int argc, char **argv)
 
   parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,
                       usage, AUTHORS, (char const *) NULL);
-  if (getopt_long (argc, argv, "", NULL, NULL) != -1)
+  if (getopt_long (argc, argv, "", long_options, NULL) != -1)
     usage (EXIT_FAILURE);
 
   switch (argc - optind)
diff --git a/src/whoami.c b/src/whoami.c
index 161674c67..69f3a0262 100644
--- a/src/whoami.c
+++ b/src/whoami.c
@@ -35,6 +35,11 @@
 
 #define AUTHORS proper_name ("Richard Mlynarik")
 
+static struct option const long_options[] =
+{
+  {NULL, 0, NULL, 0}
+};
+
 void
 usage (int status)
 {
@@ -72,7 +77,7 @@ main (int argc, char **argv)
 
   parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,
                       usage, AUTHORS, (char const *) NULL);
-  if (getopt_long (argc, argv, "", NULL, NULL) != -1)
+  if (getopt_long (argc, argv, "", long_options, NULL) != -1)
     usage (EXIT_FAILURE);
 
   if (optind != argc)
diff --git a/src/yes.c b/src/yes.c
index 0439d0e32..8b1caa4c1 100644
--- a/src/yes.c
+++ b/src/yes.c
@@ -32,6 +32,11 @@
 
 #define AUTHORS proper_name ("David MacKenzie")
 
+static struct option const long_options[] =
+{
+  {NULL, 0, NULL, 0}
+};
+
 void
 usage (int status)
 {
@@ -69,7 +74,7 @@ main (int argc, char **argv)
 
   parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, Version,
                       usage, AUTHORS, (char const *) NULL);
-  if (getopt_long (argc, argv, "+", NULL, NULL) != -1)
+  if (getopt_long (argc, argv, "+", long_options, NULL) != -1)
     usage (EXIT_FAILURE);
 
   char **operands = argv + optind;
-- 
2.15.0

Reply via email to