commit e4810f1cdbcdfdce506563200ea99334e82bd03c
Author:     FRIGN <[email protected]>
AuthorDate: Mon Feb 29 00:45:53 2016 +0100
Commit:     sin <[email protected]>
CommitDate: Thu Mar 10 08:48:09 2016 +0000

    Support NUL-containing lines in cols(1)
    
    This required an architectural change in getlines() by also storing
    the line length.

diff --git a/README b/README
index 580caca..6152930 100644
--- a/README
+++ b/README
@@ -21,7 +21,7 @@ The following tools are implemented:
 0=*|x chroot          .
 0=*|o cksum           .
 0=*|o cmp             .
- #*|x cols            .
+0#*|x cols            .
  =*|o comm            .
 0=*|o cp              (-i)
 0=*|x cron            .
diff --git a/cols.c b/cols.c
index 6892070..ae7d5b2 100644
--- a/cols.c
+++ b/cols.c
@@ -24,7 +24,7 @@ main(int argc, char *argv[])
        FILE *fp;
        struct winsize w;
        struct linebuf b = EMPTY_LINEBUF;
-       size_t chars = 65, maxlen = 0, i, j, k, len, bytes, cols, rows;
+       size_t chars = 65, maxlen = 0, i, j, k, len, cols, rows;
        int cflag = 0, ret = 0;
        char *p;
 
@@ -63,10 +63,11 @@ main(int argc, char *argv[])
        }
 
        for (i = 0; i < b.nlines; i++) {
-               len = utflen(b.lines[i]);
-               bytes = strlen(b.lines[i]);
-               if (len && bytes && b.lines[i][bytes - 1] == '\n') {
-                       b.lines[i][bytes - 1] = '\0';
+               /* TODO: fix libutf to run utflen on a memory chunk
+                * of given size to also handle embedded NULs */
+               len = utflen(b.lines[i].data);
+               if (len && b.lines[i].data[b.lines[i].len - 1] == '\n') {
+                       b.lines[i].data[--(b.lines[i].len)] = '\0';
                        len--;
                }
                if (len > maxlen)
@@ -78,8 +79,11 @@ main(int argc, char *argv[])
 
        for (i = 0; i < rows; i++) {
                for (j = 0; j < cols && i + j * rows < b.nlines; j++) {
-                       len = utflen(b.lines[i + j * rows]);
-                       fputs(b.lines[i + j * rows], stdout);
+                       /* TODO: fix libutf to run utflen on a memory chunk
+                        * of given size to also handle embedded NULs */
+                       len = utflen(b.lines[i + j * rows].data);
+                       fwrite(b.lines[i + j * rows].data, 1,
+                              b.lines[i + j * rows].len, stdout);
                        if (j < cols - 1)
                                for (k = len; k < maxlen + 1; k++)
                                        putchar(' ');
diff --git a/libutil/getlines.c b/libutil/getlines.c
index 9842d2b..4af7a25 100644
--- a/libutil/getlines.c
+++ b/libutil/getlines.c
@@ -19,12 +19,13 @@ getlines(FILE *fp, struct linebuf *b)
                        b->lines = erealloc(b->lines, b->capacity * 
sizeof(*b->lines));
                }
                linelen = len;
-               b->lines[b->nlines - 1] = memcpy(emalloc(linelen + 1), line, 
linelen + 1);
+               b->lines[b->nlines - 1].data = memcpy(emalloc(linelen + 1), 
line, linelen + 1);
+               b->lines[b->nlines - 1].len = linelen;
        }
        free(line);
-       if (b->lines && b->nlines && linelen && b->lines[b->nlines - 1][linelen 
- 1] != '\n') {
-               b->lines[b->nlines - 1] = erealloc(b->lines[b->nlines - 1], 
linelen + 2);
-               b->lines[b->nlines - 1][linelen] = '\n';
-               b->lines[b->nlines - 1][linelen + 1] = '\0';
+       if (b->lines && b->nlines && linelen && b->lines[b->nlines - 
1].data[linelen - 1] != '\n') {
+               b->lines[b->nlines - 1].data = erealloc(b->lines[b->nlines - 
1].data, linelen + 2);
+               b->lines[b->nlines - 1].data[linelen] = '\n';
+               b->lines[b->nlines - 1].data[linelen + 1] = '\0';
        }
 }
diff --git a/text.h b/text.h
index 95d2579..99a72ff 100644
--- a/text.h
+++ b/text.h
@@ -1,7 +1,12 @@
 /* See LICENSE file for copyright and license details. */
 
+struct linebufline {
+       char *data;
+       size_t len;
+};
+
 struct linebuf {
-       char **lines;
+       struct linebufline *lines;
        size_t nlines;
        size_t capacity;
 };

Reply via email to