Use POSIX getline(3) rather than the non-standard and error-prone fgetln(3).
authorschwarze <schwarze@openbsd.org>
Sat, 4 Aug 2018 16:14:03 +0000 (16:14 +0000)
committerschwarze <schwarze@openbsd.org>
Sat, 4 Aug 2018 16:14:03 +0000 (16:14 +0000)
In part based on a diff from Lauri Tirkkonen <lotheac at iki dot fi>.
While here, significantly simplify sequential().
No objection when shown on tech@.

usr.bin/paste/paste.c

index fd51bfa..f5ec60f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: paste.c,v 1.23 2018/01/02 06:56:41 guenther Exp $     */
+/*     $OpenBSD: paste.c,v 1.24 2018/08/04 16:14:03 schwarze Exp $     */
 
 /*
  * Copyright (c) 1989 The Regents of the University of California.
@@ -104,11 +104,11 @@ parallel(char **argv)
 {
        SIMPLEQ_HEAD(, list) head = SIMPLEQ_HEAD_INITIALIZER(head);
        struct list *lp;
+       char *line, *p;
+       size_t len, linesize;
        int cnt;
-       char ch, *p;
        int opencnt, output;
-       char *buf, *lbuf;
-       size_t len;
+       char ch;
 
        for (cnt = 0; (p = *argv); ++argv, ++cnt) {
                if (!(lp = malloc(sizeof(struct list))))
@@ -123,17 +123,22 @@ parallel(char **argv)
                SIMPLEQ_INSERT_TAIL(&head, lp, entries);
        }
 
+       line = NULL;
+       linesize = 0;
+
        for (opencnt = cnt; opencnt;) {
                output = 0;
                SIMPLEQ_FOREACH(lp, &head, entries) {
-                       lbuf = NULL;
                        if (!lp->fp) {
                                if (output && lp->cnt &&
                                    (ch = delim[(lp->cnt - 1) % delimcnt]))
                                        putchar(ch);
                                continue;
                        }
-                       if (!(buf = fgetln(lp->fp, &len))) {
+                       if ((len = getline(&line, &linesize, lp->fp)) == -1) {
+                               if (ferror(lp->fp))
+                                       err(1, "%s", lp->fp == stdin ?
+                                           "getline" : lp->name);
                                if (!--opencnt)
                                        break;
                                if (lp->fp != stdin)
@@ -144,15 +149,8 @@ parallel(char **argv)
                                        putchar(ch);
                                continue;
                        }
-                       if (buf[len - 1] == '\n')
-                               buf[len - 1] = '\0';
-                       else {
-                               if ((lbuf = malloc(len + 1)) == NULL)
-                                       err(1, "malloc");
-                               memcpy(lbuf, buf, len);
-                               lbuf[len] = '\0';
-                               buf = lbuf;
-                       }
+                       if (line[len - 1] == '\n')
+                               line[len - 1] = '\0';
                        /*
                         * make sure that we don't print any delimiters
                         * unless there's a non-empty file.
@@ -164,59 +162,49 @@ parallel(char **argv)
                                                putchar(ch);
                        } else if ((ch = delim[(lp->cnt - 1) % delimcnt]))
                                putchar(ch);
-                       (void)printf("%s", buf);
-                       if (lbuf)
-                               free(lbuf);
+                       fputs(line, stdout);
                }
                if (output)
                        putchar('\n');
        }
+       free(line);
 }
 
 void
 sequential(char **argv)
 {
        FILE *fp;
+       char *line, *p;
+       size_t len, linesize;
        int cnt;
-       char ch, *p, *dp;
-       char *buf, *lbuf;
-       size_t len;
 
+       line = NULL;
+       linesize = 0;
        for (; (p = *argv); ++argv) {
-               lbuf = NULL;
                if (p[0] == '-' && !p[1])
                        fp = stdin;
                else if (!(fp = fopen(p, "r"))) {
                        warn("%s", p);
                        continue;
                }
-               if ((buf = fgetln(fp, &len))) {
-                       for (cnt = 0, dp = delim;;) {
-                               if (buf[len - 1] == '\n')
-                                       buf[len - 1] = '\0';
-                               else {
-                                       if ((lbuf = malloc(len + 1)) == NULL)
-                                               err(1, "malloc");
-                                       memcpy(lbuf, buf, len);
-                                       lbuf[len] = '\0';
-                                       buf = lbuf;
-                               }
-                               (void)printf("%s", buf);
-                               if (!(buf = fgetln(fp, &len)))
-                                       break;
-                               if ((ch = *dp++))
-                                       putchar(ch);
-                               if (++cnt == delimcnt) {
-                                       dp = delim;
-                                       cnt = 0;
-                               }
-                       }
-                       putchar('\n');
+               cnt = -1;
+               while ((len = getline(&line, &linesize, fp)) != -1) {
+                       if (line[len - 1] == '\n')
+                               line[len - 1] = '\0';
+                       if (cnt >= 0)
+                               putchar(delim[cnt]);
+                       if (++cnt == delimcnt)
+                               cnt = 0;
+                       fputs(line, stdout);
                }
+               if (ferror(fp))
+                       err(1, "%s", fp == stdin ? "getline" : p);
+               if (cnt >= 0)
+                       putchar('\n');
                if (fp != stdin)
                        (void)fclose(fp);
-               free(lbuf);
        }
+       free(line);
 }
 
 int