summaryrefslogtreecommitdiff
path: root/usr.bin/factor
diff options
context:
space:
mode:
authorGarance A Drosehn <gad@FreeBSD.org>2020-01-12 20:25:11 +0000
committerGarance A Drosehn <gad@FreeBSD.org>2020-01-12 20:25:11 +0000
commit526473251ee3dd5ab71975d6b9780e00a4660b64 (patch)
tree49301aa9dde170076705e0614f089949eb370aaf /usr.bin/factor
parentfe1274ee395845ade2fc2551afbae1784237daa7 (diff)
downloadsrc-test2-526473251ee3dd5ab71975d6b9780e00a4660b64.tar.gz
src-test2-526473251ee3dd5ab71975d6b9780e00a4660b64.zip
Notes
Diffstat (limited to 'usr.bin/factor')
-rw-r--r--usr.bin/factor/factor.617
-rw-r--r--usr.bin/factor/factor.c69
2 files changed, 67 insertions, 19 deletions
diff --git a/usr.bin/factor/factor.6 b/usr.bin/factor/factor.6
index 6d01a17c0fc0..65713131f59b 100644
--- a/usr.bin/factor/factor.6
+++ b/usr.bin/factor/factor.6
@@ -36,7 +36,7 @@
.\"
.\" chongo <for a good prime call: 391581 * 2^216193 - 1> /\oo/\
.\"
-.Dd October 10, 2002
+.Dd January 12, 2020
.Dt FACTOR 6
.Os
.Sh NAME
@@ -67,11 +67,22 @@ When
.Nm
is invoked with no arguments,
.Nm
-reads numbers, one per line, from standard input, until end of file or error.
+reads numbers, one per line, from standard input until end of file or 0
+is entered or an error occurs.
Leading white-space and empty lines are ignored.
+.Pp
Numbers may be preceded by a single
.Ql + .
+Numbers can be either decimal or hexadecimal strings where the longest
+leading substring is used.
Numbers are terminated by a non-digit character (such as a newline).
+If the string contains only decimal digits, it is treated as a
+decimal representation for a number.
+A hexadecimal string can contain an optional
+.Em 0x
+or
+.Em 0X
+prefix.
After a number is read, it is factored.
.Pp
The
@@ -89,7 +100,7 @@ The
value must not be greater than the maximum.
The default and maximum value of
.Ar stop
-is 3825123056546413050.
+is 18446744073709551615.
.Pp
When the
.Nm primes
diff --git a/usr.bin/factor/factor.c b/usr.bin/factor/factor.c
index 8908b2530f9b..4edc2ed2a72c 100644
--- a/usr.bin/factor/factor.c
+++ b/usr.bin/factor/factor.c
@@ -71,6 +71,7 @@ __FBSDID("$FreeBSD$");
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -97,15 +98,16 @@ typedef u_long BN_ULONG;
#define BN_is_one(v) (*(v) == 1)
#define BN_mod_word(a, b) (*(a) % (b))
-static int BN_dec2bn(BIGNUM **a, const char *str);
-static int BN_hex2bn(BIGNUM **a, const char *str);
+static int BN_dec2bn(BIGNUM **, const char *);
+static int BN_hex2bn(BIGNUM **, const char *);
static BN_ULONG BN_div_word(BIGNUM *, BN_ULONG);
static void BN_print_fp(FILE *, const BIGNUM *);
#endif
static void BN_print_dec_fp(FILE *, const BIGNUM *);
-
+static void convert_str2bn(BIGNUM **, char *);
+static bool is_hex_str(char *);
static void pr_fact(BIGNUM *); /* print factors of a value */
static void pr_print(BIGNUM *); /* print a prime */
static void usage(void);
@@ -148,21 +150,13 @@ main(int argc, char *argv[])
for (p = buf; isblank(*p); ++p);
if (*p == '\n' || *p == '\0')
continue;
- if (*p == '-')
- errx(1, "negative numbers aren't permitted.");
- if (BN_dec2bn(&val, buf) == 0 &&
- BN_hex2bn(&val, buf) == 0)
- errx(1, "%s: illegal numeric format.", buf);
+ convert_str2bn(&val, p);
pr_fact(val);
}
/* Factor the arguments. */
else
- for (; *argv != NULL; ++argv) {
- if (argv[0][0] == '-')
- errx(1, "negative numbers aren't permitted.");
- if (BN_dec2bn(&val, argv[0]) == 0 &&
- BN_hex2bn(&val, argv[0]) == 0)
- errx(1, "%s: illegal numeric format.", argv[0]);
+ for (p = *argv; p != NULL; p = *++argv) {
+ convert_str2bn(&val, p);
pr_fact(val);
}
exit(0);
@@ -346,7 +340,7 @@ BN_dec2bn(BIGNUM **a, const char *str)
errno = 0;
**a = strtoul(str, &p, 10);
- return (errno == 0 && (*p == '\n' || *p == '\0'));
+ return (errno == 0 ? 1 : 0); /* OpenSSL returns 0 on error! */
}
static int
@@ -356,7 +350,7 @@ BN_hex2bn(BIGNUM **a, const char *str)
errno = 0;
**a = strtoul(str, &p, 16);
- return (errno == 0 && (*p == '\n' || *p == '\0'));
+ return (errno == 0 ? 1 : 0); /* OpenSSL returns 0 on error! */
}
static BN_ULONG
@@ -370,3 +364,46 @@ BN_div_word(BIGNUM *a, BN_ULONG b)
}
#endif
+
+/*
+ * Scan the string from left-to-right to see if the longest substring
+ * is a valid hexadecimal number.
+ */
+static bool
+is_hex_str(char *str)
+{
+ char c, *p;
+ bool saw_hex = false;
+
+ for (p = str; *p; p++) {
+ if (isdigit(*p))
+ continue;
+ c = tolower(*p);
+ if (c >= 'a' && c <= 'f') {
+ saw_hex = true;
+ continue;
+ }
+ break; /* Not a hexadecimal digit. */
+ }
+ return saw_hex;
+}
+
+/* Convert string pointed to by *str to a bignum. */
+static void
+convert_str2bn(BIGNUM **val, char *p)
+{
+ int n = 0;
+
+ if (*p == '+') p++;
+ if (*p == '-')
+ errx(1, "negative numbers aren't permitted.");
+ if (*p == '0') {
+ p++;
+ if (*p == 'x' || *p == 'X')
+ n = BN_hex2bn(val, ++p);
+ } else {
+ n = is_hex_str(p) ? BN_hex2bn(val, p) : BN_dec2bn(val, p);
+ }
+ if (n == 0)
+ errx(1, "%s: illegal numeric format.", p);
+}