Newsgroup: it.comp.lang.c
Titolo: svuotare buffer stdin?

Ho un programma in C e OpenGL (freeglut) che disegna una finestra in cui
fa del rendering, poi alla pressione di un certo tasto esegue un fork()
e il processo figlio esegue un programma su shell mentre il padre
aspetta con waitpid.
Mentre il padre è in attesa, se premo dei tasti sulla tastiera non
accade nulla, ma non appena il figlio termina e il controllo passa di
nuovo al padre tutto il buffer dello stdin si svuota su di esso (intendo
che processa in un colpo tutti i tasti che ho premuto mentre attendeva
il figlio).
Ho fatto una cosa del genere:
pid_t pid;
pid = fork();
switch (pid) {
	case -1:
		printf("Error: cannot create process %d\n", pid);
		break;
	case 0:
		execl(PATH, "command", NULL);
		break;
	default:
		fclose(stdin);
		waitpid(pid, NULL, 0);
		fopen("stdin", "r");
}
cercando di chiudere lo stdin prima del wait e riaprirlo dopo, ma temo
sia un pasticcio inutile (oltre a non funzionare!).
Come dovrei procedere?
Grazie!
Heruan

 Come dovrei procedere?
Qui siamo OT, comunque...
devi svuotare il buffer di input usando - ad esempio - la getchar() per 
scartare i caratteri fintanto ce ne sia uno in attesa. Ovviamente la 
getchar() e' bloccante quindi, prima di invocarla, devi controllare se 
ci sono dati "pronti" da essere eliminati.
Per questa operazione, su Unix/Linux, puoi usare la "select" con un 
breve timeout (vedi anche l'esempio in "man 2 select").
Riassumendo devi fare qualcosa del genere (codice x Linux):
//-----------------------------------------
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
/* restituisce 'non 0' se nello stdin ci sono caratteri
pronti (semplificando, qui anche su errore restituisce 0) */
int stdin_ch_ready(void)
{
         fd_set rds;
         struct timeval tv;
         FD_ZERO(&rds);
         FD_SET(fileno(stdin), &rds);
         tv.tv_sec = 1;  /* timeout di 1 secondo */
         tv.tv_usec = 0;
         return (select(fileno(stdin)+1, &rds, NULL, NULL, &tv) > 0);
}
/* la nostra funzione che svuota lo stdin */
void stdin_flushout(void)
{
         while(stdin_ch_ready())
                 getchar();
}
/* esempio */
int main(void)
{
         pid_t pid;
         pid = fork();
         switch (pid)
         {       case -1:
                         printf("Errore: fork fallita.\n");
                         break;
                 case 0:
                         printf("[%d] Processo figlio\n", getpid());
                         system("sleep 5"); /* lancia un processo bash */
                         exit(0);
                 default:
                         printf("[%d] Processo padre che attende il 
figlio %d\n", getpid(), pid);
                         fflush(stdout); /* stampa subito il messaggio 
sopra */
                         waitpid(pid, NULL, 0);
                         stdin_flushout(); /* svuota buffer di input */
                         printf("[%d] Attesa processo figlio finita.\n", 
getpid());
                         break;
         }
         return 0;
}
//--------------------
Ciao
-- 
Cybertoldo
Per rispondermi via email, sostituisci moc.liamg con 
gmail.com

 
[CUT]
Ti ringrazio!
Non ho capito come mai ero OT, in ogni caso chiedo scusa!
Ciao!

 Ciao!
ciao


 il figlio).
c'era la funzione _fpurge() o fpurge() non mi ricordo, in stdio_ex o 
qualcosa del genere, neanche quello mi ricordo... pero' esiste una funzione
mi ricordo pero' che non risolveva appieno il mio problema (ne avevo uno 
analogo)
senno' potresti provare sovrascrivendo il file descriptor 0 con quello di 
una pipe che poi
butterai, in questo modo in teoria lo stdin non accumula niente, lo accumula 
la pipe
in teoria eh :)

 }
1) In questa funzione ho usato erroneamente la getchar(). E' evidente 
che ci puo' essere discrepanza tra il buffer di input della 'stdio' con 
quello di input I/O (dove stiamo agendo). Andrebbe quindi utilizzata una 
read() a basso livello (anch'essa non portabile).
2) Anche il buffer stdin dello 'stdio' andrebbe probabilmente 
svuotato... ma e' un'operazione altamente sconsigliata dalle 'buone 
regole'. Quindi, anche per risolvere questo caso, dobbiamo essere 
altamente consapevoli di fare una schifezza dovendo usare funzioni 
deprecate e assolutamente non portabili come la __fpurge() della lib gcc 
di Linux (o la purge() di altri Unix).
Il risultato della correzione, con tutte le avvertenze del caso, sarebbe 
quindi questo:
...
#include <stdio_ext.h>
...
void stdin_flushout(void)
{       char ch;
         while(stdin_ch_ready())
                 read(fileno(stdin), &ch, 1);
         __fpurge(stdin);
}
Cosi' funziona meglio. Ma il codice e' ovviamente piu' una pezza che 
altro (ormai avevo fatto danno :-) ) Sconsiglio altamente di prenderlo 
come una pratica comune per risolvere questi casi.


 analogo)
...non risolvi il problema vuotando il buffer 'stdio' di stdin se prima 
questo non viene utilizzato per la lettura (e quindi riempito con 
l'input in coda).
Cioe', ti stai sforzando di trovare una soluzione per vuotare il secchio 
(che probabilmente e' gia' vuoto) senza pero' attingere l'acqua dal 
pozzo ;-)
Ciao


 dal pozzo ;-)
Lo so. Se il buffer č vuoto che lo svuoti a fare?? Ovviamente si deve usare 
quella
funzione quando lo stdin č pieno