plistutil: Read STDIN in chunks instead of 1 byte at a time
diff --git a/tools/plistutil.c b/tools/plistutil.c
index 6e697cf..bdf195e 100644
--- a/tools/plistutil.c
+++ b/tools/plistutil.c
@@ -246,45 +246,49 @@
             return 1;
         }
         plist_entire[read_size] = '\0';
-        char ch;
-        while(read(STDIN_FILENO, &ch, 1) > 0)
-        {
-            if (read_size >= read_capacity) {
-                char *old = plist_entire;
-                read_capacity += 4096;
-                plist_entire = realloc(plist_entire, sizeof(char) * read_capacity);
-                if (plist_entire == NULL)
-                {
-                    fprintf(stderr, "ERROR: Failed to reallocate stdin buffer\n");
-                    free(old);
-                    free(options);
-                    return 1;
-                }
-            }
-            plist_entire[read_size] = ch;
-            read_size++;
-        }
-        if (read_size >= read_capacity) {
-            char *old = plist_entire;
-            plist_entire = realloc(plist_entire, sizeof(char) * (read_capacity+1));
-            if (plist_entire == NULL)
-            {
-                fprintf(stderr, "ERROR: Failed to reallocate stdin buffer\n");
-                free(old);
-                free(options);
-                return 1;
-            }
-        }
-        plist_entire[read_size] = '\0';
+        char buf[4096];
+        ssize_t n;
 
-        // Not positive we need this, but it doesnt seem to hurt lol
-        if(ferror(stdin))
-        {
-            fprintf(stderr, "ERROR: reading from stdin.\n");
+        while (1) {
+            n = read(STDIN_FILENO, buf, sizeof(buf));
+            if (n > 0) {
+                size_t needed = read_size + (size_t)n + 1;
+                if (needed > read_capacity) {
+                    size_t newcap = read_capacity ? read_capacity : 4096;
+                    while (newcap < needed) {
+                        newcap *= 2;
+                    }
+
+                    char *tmp = realloc(plist_entire, newcap);
+                    if (!tmp) {
+                        fprintf(stderr, "ERROR: Failed to reallocate stdin buffer\n");
+                        free(plist_entire);
+                        free(options);
+                        return 1;
+                    }
+                    plist_entire = tmp;
+                    read_capacity = newcap;
+                }
+
+                memcpy(plist_entire + read_size, buf, (size_t)n);
+                read_size += (size_t)n;
+                continue;
+            }
+
+            if (n == 0) { // EOF
+                break;
+            }
+
+            // n < 0: error
+            if (errno == EINTR)
+                continue;
+
+            fprintf(stderr, "ERROR: Failed to read from stdin\n");
             free(plist_entire);
             free(options);
             return 1;
         }
+        plist_entire[read_size] = '\0';
     }
     else
     {