Stai eseguendo l'IO in modo errato, il manuale POSIX e tutta l'altra documentazione correlata dicono esplicitamente di non mescolare mai l'IO fatto su FILE *
se descrittori di file. Hai infranto palesemente questa regola. Questa regola è in vigore perché FILE *
s usa il buffering an this significa che dopo una chiamata a fgets
non rimarrà nulla per read
per ottenere perché fgets
ha già letto tutti i dati in attesa in un buffer conservato nel FILE *
struttura.
Quindi, poiché non c'è modo di verificare se un metodo ISO C IO si bloccherà, dobbiamo usare solo i descrittori di file.
Poiché sappiamo che STDIN_FILENO
è solo il numero 0, possiamo usare
fcntl (0, F_SETFL, O_NONBLOCK);
questo trasformerà tutti i read
s sul descrittore di file 0 in modalità non bloccante, se vuoi utilizzare un descrittore di file diverso in modo da poter lasciare solo 0, usa semplicemente dup
per duplicarlo.
In questo modo, puoi stare lontano da poll
completamente e implementare ngetc
come
ssize_t
ngetc (char *c)
{
return read (0, c, 1);
}
o meglio ancora, una macro
#define ngetc(c) (read (0, (c), 1))
In questo modo ottieni una semplice implementazione per ciò che stai cercando.
Modifica: Se sei ancora preoccupato per il terminale che bufferizza l'input, puoi sempre modificare le impostazioni del terminale, vedi Come disabilitare il buffering di riga dell'input in xterm dal programma? per ulteriori informazioni su come eseguire questa operazione.
Modifica: Il motivo per cui non si poteva usare fgetc
invece di read
è per lo stesso motivo per cui si utilizza fgets
non funzionerà. Quando uno dei FILE *
funzioni IO viene eseguito, legge tutti i dati dal descrittore di file associato. Ma una volta che ciò accade, poll
non tornerà mai perché è in attesa di un descrittore di file che è sempre vuoto, e la stessa cosa accadrà con read
. Pertanto, ti suggerisco di seguire i consigli della documentazione e mai mescolare stream (IO usando fgets
, fgetc
, ecc.) e descrittori di file (IO usando read
, write
, ecc.)