+/*
+ * Routines to parse numerical command-line arguments and check for
+ * errors, including "too large for that type".
+ */
+static int
+parse_int(const char *argname, const char *string, char **endpp,
+ int minval, int maxval, int base)
+{
+ long val;
+ char *endp;
+
+ errno = 0;
+ val = strtol(string, &endp, base);
+
+ /*
+ * Did it either not parse any of the string, find extra stuff
+ * at the end that the caller isn't interested in, or get
+ * another parsing error?
+ */
+ if (string == endp || (endpp == NULL && *endp != '\0') ||
+ (val == 0 && errno == EINVAL)) {
+ error("invalid %s \"%s\" (not a valid number)", argname,
+ string);
+ }
+
+ /*
+ * Did it get a value that's out of range?
+ */
+ if (((val == LONG_MAX || val == LONG_MIN) && errno == ERANGE) ||
+ val < minval || val > maxval) {
+ error("invalid %s %s (must be >= %d and <= %d)",
+ argname, string, minval, maxval);
+ }
+
+ /*
+ * OK, it passes all the tests.
+ */
+ if (endpp != NULL)
+ *endpp = endp;
+ return ((int)val);
+}
+
+static u_int
+parse_u_int(const char *argname, const char *string, char **endpp,
+ u_int minval, u_int maxval, int base)
+{
+ unsigned long val;
+ char *endp;
+
+ errno = 0;
+
+ /*
+ * strtoul() does *NOT* report an error if the string
+ * begins with a minus sign. We do.
+ */
+ if (*string == '-') {
+ error("invalid %s \"%s\" (not a valid unsigned number)",
+ argname, string);
+ }
+
+ val = strtoul(string, &endp, base);
+
+ /*
+ * Did it either not parse any of the string, find extra stuff
+ * at the end that the caller isn't interested in, or get
+ * another parsing error?
+ */
+ if (string == endp || (endpp == NULL && *endp != '\0') ||
+ (val == 0 && errno == EINVAL)) {
+ error("invalid %s \"%s\" (not a valid unsigned number)",
+ argname, string);
+ }
+
+ /*
+ * Did it get a value that's out of range?
+ */
+ if ((val == ULONG_MAX && errno == ERANGE) ||
+ val < minval || val > maxval) {
+ error("invalid %s %s (must be >= %u and <= %u)",
+ argname, string, minval, maxval);
+ }
+
+ /*
+ * OK, it passes all the tests.
+ */
+ if (endpp != NULL)
+ *endpp = endp;
+ return ((u_int)val);
+}
+
+static int64_t
+parse_int64(const char *argname, const char *string, char **endpp,
+ int64_t minval, int64_t maxval, int base)
+{
+ intmax_t val;
+ char *endp;
+
+ errno = 0;
+ val = strtoimax(string, &endp, base);
+
+ /*
+ * Did it either not parse any of the string, find extra stuff
+ * at the end that the caller isn't interested in, or get
+ * another parsing error?
+ */
+ if (string == endp || (endpp == NULL && *endp != '\0') ||
+ (val == 0 && errno == EINVAL)) {
+ error("invalid %s \"%s\" (not a valid number)", argname,
+ string);
+ }
+
+ /*
+ * Did it get a value that's out of range?
+ */
+ if (((val == INTMAX_MAX || val == INTMAX_MIN) && errno == ERANGE) ||
+ val < minval || val > maxval) {
+ error("invalid %s %s (must be >= %" PRId64 " and <= %" PRId64 ")",
+ argname, string, minval, maxval);
+ }
+
+ /*
+ * OK, it passes all the tests.
+ */
+ if (endpp != NULL)
+ *endpp = endp;
+ return ((int64_t)val);
+}
+