s = realloc(s, cap+1);

FAQ explains why this could be a bad idea - if realloc fails the original pointer is lost

also there is no check for return value of realloc at all

and fgetc returns...