diff options
author | Aaron Campbell <aaron@cvs.openbsd.org> | 2000-06-04 23:52:20 +0000 |
---|---|---|
committer | Aaron Campbell <aaron@cvs.openbsd.org> | 2000-06-04 23:52:20 +0000 |
commit | bcb5ce7f6b0a8daa3c1e0771f1cb09000b3db0da (patch) | |
tree | 8cb7f39bd60cbded8962f37f2db7ce5e41d4f9cf /usr.bin/cut | |
parent | 5f8ce151040563fc391ecc617ce828a11cb01ac6 (diff) |
Handle the case where the last line of input does not contain a newline; issue
reported by marc@snafu.org. The main thing here is we use fgetln() instead of
fgets(), also giving us the advantage of being able to handle lines of
unlimited length. Some -Wall and other fixes from millert@ as well.
Diffstat (limited to 'usr.bin/cut')
-rw-r--r-- | usr.bin/cut/cut.c | 44 |
1 files changed, 30 insertions, 14 deletions
diff --git a/usr.bin/cut/cut.c b/usr.bin/cut/cut.c index 68a2bf68a74..4aa89e0cfe9 100644 --- a/usr.bin/cut/cut.c +++ b/usr.bin/cut/cut.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cut.c,v 1.6 1998/11/28 03:41:46 aaron Exp $ */ +/* $OpenBSD: cut.c,v 1.7 2000/06/04 23:52:19 aaron Exp $ */ /* $NetBSD: cut.c,v 1.9 1995/09/02 05:59:23 jtc Exp $ */ /* @@ -47,7 +47,7 @@ static char copyright[] = #if 0 static char sccsid[] = "@(#)cut.c 8.3 (Berkeley) 5/4/95"; #endif -static char rcsid[] = "$OpenBSD: cut.c,v 1.6 1998/11/28 03:41:46 aaron Exp $"; +static char rcsid[] = "$OpenBSD: cut.c,v 1.7 2000/06/04 23:52:19 aaron Exp $"; #endif /* not lint */ #include <ctype.h> @@ -153,7 +153,7 @@ get_list(list) * overlapping lists. We also handle "-3-5" although there's no * real reason too. */ - for (; p = strsep(&list, ", \t");) { + while ((p = strsep(&list, ", \t"))) { setautostart = start = stop = 0; if (*p == '-') { ++p; @@ -182,7 +182,8 @@ get_list(list) stop, _POSIX2_LINE_MAX); if (maxval < stop) maxval = stop; - for (pos = positions + start; start++ <= stop; *pos++ = 1); + for (pos = positions + start; start++ <= stop; *pos++ = 1) + ; } /* overlapping ranges */ @@ -213,12 +214,14 @@ c_cut(fp, fname) if (*pos++) (void)putchar(ch); } - if (ch != '\n') + if (ch != '\n') { if (autostop) while ((ch = getc(fp)) != EOF && ch != '\n') (void)putchar(ch); else - while ((ch = getc(fp)) != EOF && ch != '\n'); + while ((ch = getc(fp)) != EOF && ch != '\n') + ; + } (void)putchar('\n'); } } @@ -231,19 +234,27 @@ f_cut(fp, fname) register int ch, field, isdelim; register char *pos, *p, sep; int output; - char lbuf[_POSIX2_LINE_MAX + 1]; + size_t len; + char *lbuf, *tbuf; - for (sep = dchar; fgets(lbuf, sizeof(lbuf), fp);) { + for (sep = dchar, tbuf = NULL; (lbuf = fgetln(fp, &len));) { output = 0; + if (lbuf[len - 1] != '\n') { + /* no newline at the end of the last line so add one */ + if ((tbuf = (char *)malloc(len + 1)) == NULL) + err(1, NULL); + memcpy(tbuf, lbuf, len); + tbuf[len] = '\n'; + lbuf = tbuf; + } for (isdelim = 0, p = lbuf;; ++p) { - if (!(ch = *p)) - errx(1, "%s: line too long.", fname); + ch = *p; /* this should work if newline is delimiter */ if (ch == sep) isdelim = 1; if (ch == '\n') { if (!isdelim && !sflag) - (void)printf("%s", lbuf); + (void)fwrite(lbuf, len, 1, stdout); break; } } @@ -258,20 +269,25 @@ f_cut(fp, fname) while ((ch = *p++) != '\n' && ch != sep) (void)putchar(ch); } else - while ((ch = *p++) != '\n' && ch != sep); + while ((ch = *p++) != '\n' && ch != sep) + ; if (ch == '\n') break; } - if (ch != '\n') + if (ch != '\n') { if (autostop) { if (output) (void)putchar(sep); for (; (ch = *p) != '\n'; ++p) (void)putchar(ch); } else - for (; (ch = *p) != '\n'; ++p); + for (; (ch = *p) != '\n'; ++p) + ; + } (void)putchar('\n'); } + if (tbuf) + free(tbuf); } void |