summary refs log tree commit diff
path: root/bin/hi.c
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2019-02-12 03:34:00 -0500
committerJune McEnroe <june@causal.agency>2019-02-12 03:34:00 -0500
commit68d5b021f20d8e07731f237acf452be1a636858f (patch)
treebfdbc63e76f06b2ebf22a8c1cd8872a52325b3ed /bin/hi.c
parentDon't match Rust raw strings inside other strings (diff)
downloadsrc-68d5b021f20d8e07731f237acf452be1a636858f.tar.gz
src-68d5b021f20d8e07731f237acf452be1a636858f.zip
Use a proper fread-realloc loop in hi
Diffstat (limited to 'bin/hi.c')
-rw-r--r--bin/hi.c22
1 files changed, 13 insertions, 9 deletions
diff --git a/bin/hi.c b/bin/hi.c
index de3da231..9ac3851e 100644
--- a/bin/hi.c
+++ b/bin/hi.c
@@ -682,18 +682,22 @@ int main(int argc, char *argv[]) {
 	}
 	if (!opts[Title]) opts[Title] = name;
 
-	size_t len = 32 * 1024;
-	if (file != stdin) {
-		struct stat stat;
-		int error = fstat(fileno(file), &stat);
-		if (error) err(EX_IOERR, "fstat");
-		len = stat.st_size;
-	}
+	struct stat stat;
+	int error = fstat(fileno(file), &stat);
+	if (error) err(EX_IOERR, "fstat");
 
-	char *str = malloc(len + 1);
+	size_t cap = (stat.st_mode & S_IFREG ? stat.st_size + 1 : 4096);
+	char *str = malloc(cap);
 	if (!str) err(EX_OSERR, "malloc");
 
-	len = fread(str, 1, len, file);
+	size_t len = 0, read;
+	while (0 < (read = fread(&str[len], 1, cap - len - 1, file))) {
+		len += read;
+		if (len + 1 < cap) continue;
+		cap *= 2;
+		str = realloc(str, cap);
+		if (!str) err(EX_OSERR, "realloc");
+	}
 	if (ferror(file)) err(EX_IOERR, "fread");
 	str[len] = '\0';