major stdio overhaul, using readv/writev, plus other changes
[musl] / src / stdio / fgets.c
index 7939303..3135a69 100644 (file)
@@ -7,12 +7,17 @@ char *fgets(char *s, int n, FILE *f)
        char *p = s;
        unsigned char *z;
        size_t k;
+       int c;
 
-       if (!n--) return 0;
+       if (n--<=1) {
+               if (n) return 0;
+               *s = 0;
+               return s;
+       }
 
        FLOCK(f);
 
-       while (n && !feof(f)) {
+       while (n) {
                z = memchr(f->rpos, '\n', f->rend - f->rpos);
                k = z ? z - f->rpos + 1 : f->rend - f->rpos;
                k = MIN(k, n);
@@ -20,15 +25,19 @@ char *fgets(char *s, int n, FILE *f)
                f->rpos += k;
                p += k;
                n -= k;
-               if (z) break;
-               __underflow(f);
+               if (z || !n) break;
+               if ((c = getc_unlocked(f)) < 0) {
+                       if (p==s || !feof(f)) s = 0;
+                       break;
+               }
+               n--;
+               if ((*p++ = c) == '\n') break;
        }
        *p = 0;
-       if (ferror(f)) p = s;
 
        FUNLOCK(f);
 
-       return (p == s) ? 0 : s;
+       return s;
 }
 
 weak_alias(fgets, fgets_unlocked);