This adjusts the error messages to be a bit more descriptive. Here are
the previous errors:

  $ LC_ALL=C src/stdbuf-prev -o1a true
  stdbuf-prev: invalid mode '1a'
  $ LC_ALL=C src/stdbuf-prev -oa true
  stdbuf-prev: invalid mode 'a'
  $ LC_ALL=C src/stdbuf-prev -o1Z true
  stdbuf-prev: invalid mode '1Z': Value too large for defined data type

Here are the new errors:

  $ LC_ALL=C src/stdbuf -o1a true
  stdbuf: invalid suffix in -o argument '1a'
  $ LC_ALL=C src/stdbuf -oa true
  stdbuf: invalid -o argument 'a'
  $ LC_ALL=C src/stdbuf -o1Z true
  stdbuf: -o argument '1Z' too large

* src/stdbuf.c: Include xstrtol-error.h.
(parse_size): Return the error from xstrtoumax. Prefer ckd_add to check
for overflow.
(main): Prefer xstrtol_fatal to a custom error message.
---
 src/stdbuf.c | 30 ++++++++++++++----------------
 1 file changed, 14 insertions(+), 16 deletions(-)

diff --git a/src/stdbuf.c b/src/stdbuf.c
index fb7de79b3..10b8ed73e 100644
--- a/src/stdbuf.c
+++ b/src/stdbuf.c
@@ -26,6 +26,7 @@
 #include "filenamecat.h"
 #include "quote.h"
 #include "xreadlink.h"
+#include "xstrtol-error.h"
 #include "xstrtol.h"
 #include "c-ctype.h"
 
@@ -56,28 +57,20 @@ static struct option const longopts[] =
 
 /* Set size to the value of STR, interpreted as a decimal integer,
    optionally multiplied by various values.
-   Return -1 on error, 0 on success.
+   Return LONGINT_OK on success, otherwise an error for use with
+   xstrtol_fatal.
 
    This supports dd BLOCK size suffixes.
    Note we don't support dd's b=512, c=1, w=2 or 21x512MiB formats.  */
-static int
+static enum strtol_error
 parse_size (char const *str, size_t *size)
 {
   uintmax_t tmp_size;
   enum strtol_error e = xstrtoumax (str, NULL, 10,
                                     &tmp_size, "EGkKMPQRTYZ0");
-  if (e == LONGINT_OK && SIZE_MAX < tmp_size)
+  if (e == LONGINT_OK && ckd_add (size, tmp_size, 0))
     e = LONGINT_OVERFLOW;
-
-  if (e == LONGINT_OK)
-    {
-      errno = 0;
-      *size = tmp_size;
-      return 0;
-    }
-
-  errno = (e == LONGINT_OVERFLOW ? EOVERFLOW : errno);
-  return -1;
+  return e;
 }
 
 void
@@ -329,6 +322,7 @@ main (int argc, char **argv)
 
   while ((c = getopt_long (argc, argv, "+i:o:e:", longopts, NULL)) != -1)
     {
+      int const oi = -1;
       int opt_fileno;
 
       switch (c)
@@ -352,9 +346,13 @@ main (int argc, char **argv)
               usage (EXIT_CANCELED);
             }
 
-          if (!streq (optarg, "L")
-              && parse_size (optarg, &stdbuf[opt_fileno].size) == -1)
-            error (EXIT_CANCELED, errno, _("invalid mode %s"), quote (optarg));
+          if (!streq (optarg, "L"))
+            {
+              enum strtol_error e = parse_size (optarg,
+                                                &stdbuf[opt_fileno].size);
+              if (e != LONGINT_OK)
+                xstrtol_fatal (e, oi, c, longopts, optarg);
+            }
 
           break;
 
-- 
2.55.0


Reply via email to