The problem you are having is that terminals don't have EOFs -- they're not files, so "end of file" doesn't really make any sense. Instead, they have EOT (end of transmission -- Ctrl+D), which generally registers as an EOF to stdio due to a (happy?) accident.
Files on UNIX signal EOF by returning a size 0 read, and stdio treats any size 0 read as an EOF regardless of whether it is reading from a file or not. EOT causes a terminal to return immediately, which will be a size 0 read (triggering an EOF in stdio) if and only if the input buffer is empty.
The easiest solution is not to worry about it -- just let the user hit Ctrl+D multiple times if they want to signal an EOF here. It should only require two, unless you have odd timing issues going on.
If you really want to, you can attempt to figure out if an EOT was hit -- if the result of fgets does not fill the buffer and does not end with a newline, then the user hit EOT to transmit it, so you could test for that and break out of the loop. This fails if the user enters exactly enough data to fill the fgets buffer and then hits EOT. It can also fail if the user is "typing" too fast for the program to keep up (an EOT while the program is not actually waiting for input has no effect). I say "typing" since the terminal might be a pseudo-terminal with something faking very fast input on the other end (including EOTs)