>何文字かに続けてCTRL-Dなら、NULLにならないのは当然だろ?

はい。man fgets によれば、fgets() が NULL を返すのは、エラーか、
一文字も読まずにEOFになった場合。文字を読んだ後 EOF になっても NULL を
返さないのはマニュアルどおりです。質問は、EOF にするのになぜ Ctrl-D が
2回要るか、ということでした。

>Ctrl-D の扱いは端末のお話になってくるので UNIX の本とか読んでみたり.

本を読んだわけではありませんが、ネットで少し調べると、どうも端末のバッファリングが
関係しているようでした。

abc と入力したあと、ctrl-D や RET を押す前なら、backspace で修正等が出来る。
ctrl-D を押すと、現在のバッファの内容が送られ、バッファは空になる。
バッファが空の時に ctrl-D を押すと、EOF になる。
バッファが空なのは、行頭か、ctrl-D を押した直後。
どうもこういうことらしいです。(私の理解が正しければ)