Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 23 Apr 2001 20:54:05 -0700 (PDT)
From:      dd@freebsd.org
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   bin/26810: [PATCH] make cut(1) work with long lines
Message-ID:  <200104240354.f3O3s5914785@spike.unixfreak.org>

next in thread | raw e-mail | index | archive | help

>Number:         26810
>Category:       bin
>Synopsis:       [PATCH] make cut(1) work with long lines
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Mon Apr 23 21:00:01 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     Dima Dorfman
>Release:        FreeBSD 5.0-20010407-CURRENT i386
>Organization:
Private
>Environment:
System: FreeBSD spike.unixfreak.org 5.0-20010407-CURRENT FreeBSD 5.0-20010407-CURRENT #59: Sat Apr 21 00:18:59 PDT 2001 dima@spike.unixfreak.org:/c/home/dima/w/f/src/sys/compile/SPIKE i386

>Description:

cut(1) cannot deal with lines longer than 2048 characters, and does
not properly deal with files that do not have a trailing newline.

>How-To-Repeat:

dima@spike% perl -e 'for ($i = 0; $i < 9000; $i++) { print "magic$i " }' > llt
dima@spike% cut -d\  -f2 llt
cut: llt: line too long.
dima@spike% echo -n "file with no trailing newline" > ntn
dima@spike% cut -d\  -f2 ntn
cut: ntn: line too long.
dima@spike%

>Fix:

The following patch fixes both of the cases described above.  Note
that specifying a list over 2048 on the command line (e.g., the -f
option) still isn't supported, but at least cut(1) doesn't choke when
you want the second token but feed it a few thousand characters in one
line.

Index: cut.c
===================================================================
RCS file: /st/src/FreeBSD/src/usr.bin/cut/cut.c,v
retrieving revision 1.12
diff -u -r1.12 cut.c
--- cut.c	2001/02/06 20:03:48	1.12
+++ cut.c	2001/04/20 20:49:08
@@ -43,6 +43,7 @@
   "$FreeBSD: src/usr.bin/cut/cut.c,v 1.12 2001/02/06 20:03:48 charnier Exp $";
 #endif /* not lint */
 
+#include <assert.h>
 #include <ctype.h>
 #include <err.h>
 #include <limits.h>
@@ -228,19 +229,30 @@
 	int ch, field, isdelim;
 	char *pos, *p, sep;
 	int output;
-	char lbuf[_POSIX2_LINE_MAX + 1];
+	char *lbuf, *mlbuf = NULL;
+	size_t lbuflen;
 
-	for (sep = dchar; fgets(lbuf, sizeof(lbuf), fp);) {
+	for (sep = dchar; (lbuf = fgetln(fp, &lbuflen)) != NULL;) {
+		/* Assert EOL has a newline. */
+		if (*(lbuf + lbuflen - 1) != '\n') {
+			/* Can't have > 1 line with no trailing newline. */
+			assert(mlbuf == NULL);
+			mlbuf = malloc(lbuflen + 1);
+			if (mlbuf == NULL)
+				err(1, "malloc");
+			memcpy(mlbuf, lbuf, lbuflen);
+			*(mlbuf + lbuflen) = '\n';
+			lbuf = mlbuf;
+		}
 		output = 0;
-		for (isdelim = 0, p = lbuf;; ++p) {
-			if (!(ch = *p))
-				errx(1, "%s: line too long.", fname);
+		for (isdelim = 0, p = lbuf; p < lbuf + lbuflen; ++p) {
+			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, lbuflen, 1, stdout);
 				break;
 			}
 		}
@@ -272,6 +284,8 @@
 		}
 		(void)putchar('\n');
 	}
+	if (mlbuf != NULL)
+		free(mlbuf);
 }
 
 static void
>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200104240354.f3O3s5914785>