summaryrefslogtreecommitdiffstats
path: root/usr.bin/jot
diff options
context:
space:
mode:
authorsheldonh <sheldonh@FreeBSD.org>2000-01-06 15:37:37 +0000
committersheldonh <sheldonh@FreeBSD.org>2000-01-06 15:37:37 +0000
commit00f970ec4339333aefd8c0022e7e1dfaa4e2e2ff (patch)
treebfa82e53256cc6f4185c5177f81551007d7d24ba /usr.bin/jot
parentfaa605e6a5eceac422c8b6064e166e34b85d48a3 (diff)
downloadFreeBSD-src-00f970ec4339333aefd8c0022e7e1dfaa4e2e2ff.zip
FreeBSD-src-00f970ec4339333aefd8c0022e7e1dfaa4e2e2ff.tar.gz
Back out rev 1.11, about which bde had concerns, and instead implement
appropriate bounds-checking and typecasts based on our knowledge of the desired conversion format specifier. Simplify diagnostics and take care to print the correct conversion format specifier when %l is involved.
Diffstat (limited to 'usr.bin/jot')
-rw-r--r--usr.bin/jot/jot.137
-rw-r--r--usr.bin/jot/jot.c101
2 files changed, 72 insertions, 66 deletions
diff --git a/usr.bin/jot/jot.1 b/usr.bin/jot/jot.1
index d8419c7..68fc42e 100644
--- a/usr.bin/jot/jot.1
+++ b/usr.bin/jot/jot.1
@@ -183,18 +183,16 @@ from column 10 and ending in column 132, use
.Pp
and to print all lines 80 characters or longer,
.Dl grep `jot -s \&"\&" -b \&. 80`
-.Pp
-.Sh SEE ALSO
-.Xr ed 1 ,
-.Xr expand 1 ,
-.Xr rs 1 ,
-.Xr yes 1 ,
-.Xr printf 3 ,
-.Xr random 3
-.Sh BUGS
-Conversion format specifiers for
+.Sh DIAGNOSTICS
+The
+.Nm
+utility exits 0 on success, and >0 if an error occurs.
+The following diagnostic messages deserve special explanation:
+.Bl -diag
+.It "illegal or unsupported format '%s'"
+The requested conversion format specifier for
.Xr printf 3
-are limited to those of the form
+was not of the form
.Dl %[#][ ][{+,-}][0-9]*[.[0-9]*]?
where
.Dq ?
@@ -202,6 +200,17 @@ must be one of
.Dl [l]{d,i,o,u,x}
or
.Dl {c,e,f,g,D,E,G,O,U,X}
-.Pp
-No bounds-checking is performed on numeric values, so arithmetic overflow
-will cause a fatal error.
+.It "range error in conversion"
+A value to be printed fell outside the range of the data type
+associated with the requested output format.
+.It "too many conversions"
+More than one conversion format specifier has been supplied,
+but only one is allowed.
+.El
+.Sh SEE ALSO
+.Xr ed 1 ,
+.Xr expand 1 ,
+.Xr rs 1 ,
+.Xr yes 1 ,
+.Xr printf 3 ,
+.Xr random 3
diff --git a/usr.bin/jot/jot.c b/usr.bin/jot/jot.c
index 12b5998..a15b83f 100644
--- a/usr.bin/jot/jot.c
+++ b/usr.bin/jot/jot.c
@@ -54,7 +54,6 @@ static const char rcsid[] =
#include <ctype.h>
#include <err.h>
#include <limits.h>
-#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -76,21 +75,18 @@ int randomize;
int infinity;
int boring;
int prec;
+int longdata;
int intdata;
int chardata;
int nosign;
int nofinalnl;
-int oflowlen;
-char *oflowstr;
char *sepstring = "\n";
char format[BUFSIZ];
-struct sigaction act, oact;
-void arith_oflow __P((int));
void getargs __P((int, char *[]));
void getformat __P((void));
int getprec __P((char *));
-void putdata __P((double, long));
+int putdata __P((double, long));
static void usage __P((void));
int
@@ -104,23 +100,18 @@ main(argc, argv)
register double *y = &yd;
register long *i = &id;
- act.sa_handler = arith_oflow;
- act.sa_flags = 0;
- sigfillset(&act.sa_mask);
- oflowstr = "caught SIGFPE: arithmetic overflow\n";
- oflowlen = strlen(oflowstr);
- if (sigaction(SIGFPE, &act, &oact))
- err(1, "loading SIGFPE handler");
getargs(argc, argv);
if (randomize) {
*x = (ender - begin) * (ender > begin ? 1 : -1);
for (*i = 1; *i <= reps || infinity; (*i)++) {
*y = (double) arc4random() / ULONG_MAX;
- putdata(*y * *x + begin, reps - *i);
+ if (putdata(*y * *x + begin, reps - *i))
+ errx(1, "range error in conversion");
}
} else
for (*i = 1, *x = begin; *i <= reps || infinity; (*i)++, *x += s)
- putdata(*x, reps - *i);
+ if (putdata(*x, reps - *i))
+ errx(1, "range error in conversion");
if (!nofinalnl)
putchar('\n');
exit(0);
@@ -317,24 +308,41 @@ getargs(ac, av)
infinity = 1;
}
-void
+int
putdata(x, notlast)
double x;
long notlast;
{
- if (boring) /* repeated word */
+ if (boring)
printf(format);
- else if (chardata) /* character representation */
- printf(format, (int)x);
- else if (intdata && nosign) /* scalar */
- printf(format, (unsigned long)x);
- else if (intdata)
- printf(format, (long)x);
- else /* real */
+ else if (longdata && nosign) {
+ if (x <= (double)ULONG_MAX && x >= (double)0)
+ printf(format, (unsigned long)x);
+ else
+ return (1);
+ } else if (longdata) {
+ if (x <= (double)LONG_MAX && x >= (double)LONG_MIN)
+ printf(format, (long)x);
+ else
+ return (1);
+ } else if (chardata || (intdata && !nosign)) {
+ if (x <= (double)INT_MAX && x >= (double)INT_MIN)
+ printf(format, (int)x);
+ else
+ return (1);
+ } else if (intdata) {
+ if (x <= (double)UINT_MAX && x >= (double)0)
+ printf(format, (unsigned int)x);
+ else
+ return (1);
+
+ } else
printf(format, x);
if (notlast != 0)
fputs(sepstring, stdout);
+
+ return (0);
}
static void
@@ -368,7 +376,7 @@ void
getformat()
{
register char *p;
- int dot, hash, space, sign, numbers, islong = 0;
+ int dot, hash, space, sign, numbers = 0;
char *s;
if (boring) /* no need to bother */
@@ -401,18 +409,18 @@ getformat()
((*p == '+' || *p == '-') && !(numbers|dot|sign++))
|| (*p == '.' && !(dot++)))
p++;
- else if (*p == '$' || *p == '*')
- errx(1, "unsupported format character %c", *p);
- else if (*p == '\0')
- errx(1, "missing format character");
else
- errx(1, "illegal format character %c", *p);
+ goto fmt_broken;
+ }
+ if (*p == 'l') {
+ longdata = 1;
+ if (*++p == 'l') {
+ if (p[1] != '\0')
+ p++;
+ goto fmt_broken;
+ }
}
switch (*p) {
- case 'l':
- islong = 1;
- p++;
- /* FALLTHROUGH */
case 'o': case 'u': case 'x': case 'X':
intdata = nosign = 1;
break;
@@ -420,32 +428,29 @@ getformat()
intdata = 1;
break;
case 'D':
- if (!islong) {
+ if (!longdata) {
intdata = 1;
break;
}
case 'O': case 'U':
- if (!islong) {
+ if (!longdata) {
intdata = nosign = 1;
break;
}
case 'c':
- if (!(intdata | islong)) {
+ if (!(intdata | longdata)) {
chardata = 1;
break;
}
- case 's':
- errx(1, "cannot convert numeric data to strings");
- break;
- case 'h': case 'n': case 'p': case 'q': case 'L':
+ case 'h': case 'n': case 'p': case 'q': case 's': case 'L':
case '$': case '*':
- errx(1, "unsupported format character %c", *p);
- /* NOTREACHED */
+ goto fmt_broken;
case 'f': case 'e': case 'g': case 'E': case 'G':
- if (!islong)
+ if (!longdata)
break;
/* FALLTHROUGH */
default:
+fmt_broken:
*++p = '\0';
errx(1, "illegal or unsupported format '%s'", s);
/* NOTREACHED */
@@ -461,11 +466,3 @@ getformat()
}
}
}
-
-void
-arith_oflow(int sig)
-{
-
- write(STDERR_FILENO, oflowstr, oflowlen);
- _exit(sig);
-}
OpenPOWER on IntegriCloud