Estás haciendo IO incorrectamente, el manual POSIX y toda la documentación relacionada dice explícitamente que nunca mezcles IO hecho en FILE *
s y descriptores de archivos. Has roto esta regla descaradamente. Esta regla existe porque FILE *
s usar búfer y esto significa que después de una llamada a fgets
no quedará nada para read
obtener porque fgets
ya leyó todos los datos pendientes en un búfer que se guarda en el FILE *
estructura.
Entonces, dado que no hay forma de verificar si un método ISO C IO se bloqueará, solo debemos usar descriptores de archivos.
Como sabemos que STDIN_FILENO
es solo el número 0, podemos usar
fcntl (0, F_SETFL, O_NONBLOCK);
esto convertirá todos los read
s en el descriptor de archivo 0 al modo sin bloqueo, si desea usar un descriptor de archivo diferente para poder dejar 0 solo, simplemente use dup
para duplicarlo.
De esta manera, puedes mantenerte alejado de poll
completamente e implementar ngetc
como
ssize_t
ngetc (char *c)
{
return read (0, c, 1);
}
o mejor aún, una macro
#define ngetc(c) (read (0, (c), 1))
Por lo tanto, obtiene una implementación simple para lo que está buscando.
Editar: Si aún le preocupa que el terminal almacene en búfer la entrada, siempre puede cambiar la configuración del terminal, consulte ¿Cómo deshabilitar el almacenamiento en búfer de línea de entrada en xterm desde el programa? para obtener más información sobre cómo hacerlo.
Editar: La razón por la que uno no puede usar fgetc
en lugar de read
es por la misma razón que usar fgets
no funcionará Cuando uno de los FILE *
Las funciones IO se ejecutan, lee todos los datos del descriptor de archivo asociado. Pero una vez que eso sucede, poll
nunca regresará porque está esperando un descriptor de archivo que siempre está vacío, y lo mismo sucederá con read
. Por lo tanto, le sugiero que siga los consejos de la documentación y nunca mezclar flujos (IO usando fgets
, fgetc
, etc.) y descriptores de archivo (IO usando read
, write
, etc)