Вы бы одновременно считывали часть строки в буфер фиксированного размера, а затем копировали содержимое этого буфера фиксированного размера в динамически выделенный и изменяемый размер буфера:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define SIZE ... // some reasonable size to handle most cases
int getNextLine(FILE *stream, char **line, size_t *lineLength)
{
char inbuf[SIZE];
int done = 0;
int rval = 1; // success
*lineLength = 0;
/**
* If *line is not NULL, it is assumed that it was allocated on a
* previous call to getNextLine. Free it and set to NULL.
*/
if (*line != NULL)
{
free(*line);
*line = NULL;
}
while(!done)
{
char *tmp;
if (fgets(inbuf, sizeof inbuf, stream))
{
/**
* Check for newline character. If present, clear it and set the
* done flag to true.
*/
char *newline = strchr(inbuf, '\n');
if (newline != NULL)
{
*newline = 0;
done = 1;
}
/**
* Extend the dynamic buffer by the length of the input string
* and copy the input string to it.
*/
tmp = realloc(*line, *lineLength + strlen(inbuf) + 1);
if (tmp)
{
*line = tmp;
(*line)[*lineLength] = 0;
strcat(*line, inbuf);
*lineLength += strlen(inbuf) + 1;
}
else
{
printf("Error allocating or extending buffer\n");
rval = 0;
done = 1;
}
}
else
{
if (feof(stream))
{
printf("At end-of-file\n");
rval = EOF;
}
else
{
printf("Error during read\n");
rval = 0;
}
done = 1;
}
}
return rval;
}
int main(void)
{
char *line = NULL; // line *MUST* be initialized to NULL
size_t lineLength = 0;
int status;
for (;;)
{
int status = getNextLine(stdin, &line, &lineLength);
if (status == 0 || status == EOF)
break;
printf("Read %lu characters in line: \"%s\"\n",
(unsigned long) lineLength, line);
}
return 0;
}