Newsgroup: it.comp.os.linux.development
Titolo: Input da tastiera

Ebbene si', e' possibile complicarsi la vita anche con funzioni come
getchar()...
Esiste un modo (possibilmente portabile) per verificare se lo stdin (nel
caso della tastiera) contiene caratteri da leggere, senza attivare i
trap del sistema operativo?
Nel mio caso, dato che funzioni come getchar() e affini interrompono
sempre e comunque l'esecuzione del programma per richedere l'input
dell'utente, sono arrivato addirittura a rippare stdin per ottenere un
identificatore di file utilizzabile con read(), pensando di ottenere
come risultato 0 nel caso il buffer di tastiera fosse vuoto... e invece
no! Il programma viene interrotto, si e' costretti ad inserire dei
caratteri, e read() restituisce il numero di caratteri appena digitati!
Un milione di grazie a chiunque mi possa dare una mano.
Alceste


Io ho risolto il problema attraverso l'uso di fork e IPC (messaggi tra
processi), un processo fa da lettore di tasti e rimane bloccato, il
processo principale fa altre cose e a tempo legge la propria coda
messaggi (lettura non bloccante)... funziona !!!
(se sei interessato fammelo sapere che ti mando esempi in formato
sorgente)
ciao

caratteri, e read() restituisce il numero di caratteri appena digitati!
man  2 select
man 2 fcntl

caso della tastiera) contiene caratteri da leggere, senza attivare i
Beh, perchè non provare read() aprendo stdin? Il fd di stdin è 1.
-- 
		Giuseppe Corbelli
    -=< A Metal Heart Is Hard To Tear Apart >=-
ANTI-SPAM: E-Mail address is fake. Substitute cowo with IHATESPAM.

 ciao
Grazie per la risposta, se vuoi mandami pure i sorgenti...
Ma ci sara' mica speranza per una soluzione non-POSIX, portabile su
compilatori non Unix che siano ANSI o ISO compatibili?
P.S.: Chiedo scusa per non aver fatto un quote completo, ma ho dei problemi
col server NNTP...

 compilatori non Unix che siano ANSI o ISO compatibili?
Se non è posix come fa ad essere portabile?
Cmq, se non ti va gestire processi (o threads) separati ti conviene
usare le async io functions standard:
aio_read, aio_write, etc...
Per maggiori informazioni consulta la documentazione texinfo della libc:
info libc
Ciao,
Fabio Alemagna

 Alceste
Da come ti sei spiegato direi che ti basta settare il terminale... e poi
usare read().
E' già tutto pronto, per carità non occorre lanciare 2 processi e usare
IPC o 2 threads... !
Devi settare ~(ECHO | ICANON) e [VMIN],[VTIME] a zero.
Si chiama control-break mode, non occorre inventare niente...
Leggi ad esempio man termios o altro sui POSIX terminals (meglio sarebbe
lo Stevens).
Attento che se ti serve non-POSIX, può non essere (non è) portabile.
Se invece tutto questo lo sai già e non c'entra niente allora spiegati
meglio.
Ciao, oops.
(P.S.: cosa intendi per "trap del SO" ?)
(P.S.: se vuoi ti scrivo 2 righe di esempio in C (POSIX-compliant) )

 (P.S.: se vuoi ti scrivo 2 righe di esempio in C (POSIX-compliant) )
Grazie, mi faresti un enorme favore...
Alceste

 ANTI-SPAM: E-Mail address is fake. Substitute cowo with IHATESPAM.
Ma... Hai letto bene il corpo della mia richiesta? ;-)
Vabbe', grazie comunque...
Alceste

 Se non è posix come fa ad essere portabile?
Beh, il mio problema e' che devo creare un programma per un esame di
Informatica (ed io ovviamente sviluppo sutto Linux), e che questo programma
girara' sotto Winzozz 98 (AAARRGHHHH!!!!!!) quando sara' valutato. Quindi,
dato che non credo il compilatore Borland C++ 5 supporti benissimo lo
standard Posix (a parte i classici read() e write()), preferirei attenermi
allo standard ANSI C, che non sara' bellissimo ma almeno non mi dara'
problemi...
Per questo ho chiesto se esiste una soluzione standard che non sia Posix,
ma se non ci fosse, beh, pazienza...
Grazie comunque per la tua risposta, mi sara' sicuramente utilissima.
Alceste


Direi nè a nè b. Il punto è che l'I/O con alcuni file (device di
terminale, di rete e pipes) è bloccante, cioè se non c'è niente da
leggere allora read rimane in attesa (e blocca l'esecuzione del
thread/processo), analogamente write. Ci sono ottimi libri di
programmazione Unix che spiegano bene queste cose. Un classico è lo
Stevens.
stdin, stdout e stderr di un processo in esecuzione si riferiscono al
terminale su cui gira la sessione. Lo so che tu certamente non avrai
terminali collegati alla tua linux-box e starai pensando: cosa dice? Ma
le virtual consoles emulano un terminale, con tanto di settaggi del baud
rate, ad esempio.
Il kernel unix-like prevede un device driver del terminale, ed è su
quello che si può agire per settare, nel tuo caso, niente buffer e
niente blocking. Ecco il sorgente:
funzione per settare il terminale come serve a te cioè cbreak mode
no-blocking:
#include <termios.h>
#include <unistd.h>
static struct termios	backup;
int tty_cbreak (int fd)
{
	struct termios buf
	if (tcgetattr(fd, &backup) < 0)
		return(-1);
	buf = backup;
	buf.c_lflag &= ~(ECHO | ICANON);	/* no echo & no buffer */
	buf.c_cc[VMIN] = 0;	/* don't		*/
	buf.c_cc[VTIME] = 0;	/* block me please	*/
	if (tcsetattr(fd, TCSAFLUSH, &buf) <0
		return(-1);
	return(0);
}
Ecco. A parte errori di battitura dovrebbe andare, l'ho presa da un mio
sorgente che ha funzionato in passato. Eppoi in realtà l'ha scritta
Stevens.
Puoi anche mantenere l'echo, se ti serve. Vedi tu.
Prima di terminare l'esecuzione del programma è buona norma ripristinare
il settaggio del terminale per non avere problemi con la shell che ti
aspetta là fuori.
cioè fai tcsetattr(fd, TCSAFLUSH, &backup);
Dopo do ciò le tue read(STDIN_FILENO, &c, 1) ritorneranno 0 se non hanno
letto niente, 1 se hanno letto un carattere, -1 se si è verificato un
errore.
ciao e buon divertimento.
P.S. Ah, dimenticavo , ovviamente man termios spiega tutto su questi
settaggi.

 Alceste
A parte il POSIX-compliant comunque, volendo puoi usare la libreria
ncurses.
Molti sceglierebbero questa strada, io preferisco non usarla a meno che
non debba fare finestre in modalità terminale, per un semplice input da
tastiera no. Ma è questione di gusti.
Devi fare grossomodo:
#include <curses.h>
	initscr();
	cbreak();
	noecho();
fare finestre e box, tipo:
int xmax, ymax;
	getmaxyx (stdscr, ymax, xmax);
eppoi:
int c;
	c = getch()
ovviamente devi gestire gli errori.
ciao.

 Mi sbaglio?
Ti sbagli. stdin non è un file speciale, è semplicemente lo stream
associato al file descriptor 0 (o 1, ora non ricordo).
Ciao,
Fabio Alemagna