Provádíte IO nesprávně, manuál POSIX a veškerá další související dokumentace výslovně říká nikdy nesměšovat IO provedené na FILE *
s a deskriptory souborů. Toto pravidlo jste velmi očividně porušil. Toto pravidlo platí, protože FILE *
s pomocí vyrovnávací paměti a to znamená, že po volání na fgets
pro read
nezbude nic získat, protože fgets
již načetl všechna čekající data do vyrovnávací paměti, která je uložena v FILE *
struktura.
Takže protože neexistuje způsob, jak zkontrolovat, zda bude metoda ISO C IO blokována, musíme používat pouze deskriptory souborů.
Protože víme, že STDIN_FILENO
je pouze číslo 0, můžeme použít
fcntl (0, F_SETFL, O_NONBLOCK);
toto změní všech read
s na deskriptoru souboru 0 do neblokovacího režimu, pokud chcete použít jiný deskriptor souboru, abyste mohli ponechat 0, stačí použít dup
jej duplikovat.
Tímto způsobem se můžete držet dál od poll
kompletně a implementovat ngetc
jako
ssize_t
ngetc (char *c)
{
return read (0, c, 1);
}
nebo ještě lépe makro
#define ngetc(c) (read (0, (c), 1))
Získáte tak jednoduchou implementaci toho, co hledáte.
Upravit: Pokud se stále obáváte, že terminál ukládá vstup do vyrovnávací paměti, můžete kdykoli změnit nastavení terminálu, viz Jak z programu zakázat ukládání do vyrovnávací paměti řádku vstupu v xterm? pro více informací o tom, jak to provést.
Upravit: Důvod, proč nelze použít fgetc
místo read
je ze stejného důvodu jako použití fgets
nebude fungovat. Když jeden z FILE *
IO funkce jsou spuštěny, čte všechna data z přidruženého deskriptoru souboru. Ale jakmile se to stane, poll
se nikdy nevrátí, protože čeká na deskriptor souboru, který je vždy prázdný, a totéž se stane s read
. Navrhuji proto, abyste se řídili radami v dokumentaci a nikdy mix streamů (IO pomocí fgets
, fgetc
, atd.) a deskriptory souborů (IO pomocí read
, write
atd.)