diff options
author | sheldonh <sheldonh@FreeBSD.org> | 2000-01-06 15:37:37 +0000 |
---|---|---|
committer | sheldonh <sheldonh@FreeBSD.org> | 2000-01-06 15:37:37 +0000 |
commit | 00f970ec4339333aefd8c0022e7e1dfaa4e2e2ff (patch) | |
tree | bfa82e53256cc6f4185c5177f81551007d7d24ba /usr.bin/jot | |
parent | faa605e6a5eceac422c8b6064e166e34b85d48a3 (diff) | |
download | FreeBSD-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.1 | 37 | ||||
-rw-r--r-- | usr.bin/jot/jot.c | 101 |
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); -} |