continuano a coprire un ruolo particolare, restando strettamente legati al
funzionamento dell'interfaccia a linea di comando.
-Mella prima parte del capitolo esamineremo i concetti base del sistema delle
+Nella prima parte del capitolo esamineremo i concetti base del sistema delle
sessioni di lavoro, vale a dire il metodo con cui il kernel permette ad un
-utente di gestire le capacità multitiasking del sistema, permettendo di
+utente di gestire le capacità multitasking del sistema, permettendo di
eseguire più programmi in contemporanea. Nella seconda parte del capitolo
tratteremo poi il funzionamento dell'I/O su terminale, e delle varie
peculiarità che esso viene ad assumere a causa del suo stretto legame con il
Per questo motivo un programma che deve funzionare come demone deve sempre
prendere autonomamente i provvedimenti opportuni (come distaccarsi dal
terminale e dalla sessione) ad impedire eventuali interferenze da parte del
-sistema del \textit{job contol}; questi sono riassunti in una lista di
+sistema del \textit{job control}; questi sono riassunti in una lista di
prescrizioni\footnote{ad esempio sia Stevens in \cite{APUE}, che la
\textit{Unix Programming FAQ} \cite{UnixFAQ} ne riportano di sostanzialmente
identiche.} da seguire quando si scrive un demone.
\end{table}
La funzione che si usa per generare un messaggio è \func{syslog}, dato che
-l'uso di \func{openlog} è ozionale, sarà quest'ultima a provvede a chiamare la
+l'uso di \func{openlog} è opzionale, sarà quest'ultima a provvede a chiamare la
prima qualora ciò non sia stato fatto (nel qual caso il valore di
\param{ident} è nullo). Il suo prototipo è:
\begin{prototype}{syslog.h}
\subsection{L'architettura}
\label{sec:term_design}
-
-I terminali sono una classe speciale di dispositivi a caratteri (si rammenti
-la classificazione di \secref{sec:file_file_types}); un terminale ha infatti
-una caratteristica che lo contraddistingue da un qualunque altro dispositivo,
-e cioè che è destinato a gestire l'interazione con un utente (deve essere in
-grado di fare da terminale di controllo per una sessione), che comportano la
+I terminali sono una classe speciale di dispositivi a caratteri (si ricordi la
+classificazione di \secref{sec:file_file_types}); un terminale ha infatti una
+caratteristica che lo contraddistingue da un qualunque altro dispositivo, e
+cioè che è destinato a gestire l'interazione con un utente (deve essere cioè
+in grado di fare da terminale di controllo per una sessione), che comporta la
presenza di ulteriori capacità.
L'interfaccia per i terminali è una delle più oscure e complesse, essendosi
connessioni di rete (ad esempio per trattare i dati inviati con \cmd{telnet} o
\cmd{ssh}).
-% In generale tutti i terminali hanno un insieme di funzionalità comuni, che
-% vengono chiamate \textsl{discipline di linea}; esse contraddistinguono le
-% modalità con cui il kernel manipola (ad esempio la reazione ad un carattere di
-% cancellazione per la tastiera, o la gestione della linea tramite PPP o SLIP) i
-% dati grezzi che vengono immessi sul dispositivo;
-
-
-L'I/O sui terminali si effettua con le stesse modalità dei file normali, si
-apre il relativo file di dispositivo, e si leggono e scriveno i dati con le
-usuali funzioni di lettura e scrittura, occorre però tenere conto delle loro
-caratteristiche specifiche, essi infatti prevedono due modalità di operazione,
+L'I/O sui terminali si effettua con le stesse modalità dei file normali: si
+apre il relativo file di dispositivo, e si leggono e scrivono i dati con le
+usuali funzioni di lettura e scrittura, così se apriamo una console virtuale
+avremo che \func{read} leggerà quanto immesso dalla tastiera, mentre
+\func{write} scriverà sullo schermo. In realtà questo è vero solo a grandi
+linee, perché non tiene conto delle caratteristiche specifiche dei terminali;
+una delle principali infatti è che essi prevedono due modalità di operazione,
dette rispettivamente \textsl{modo canonico} e \textsl{modo non canonico}, che
-prevedono dei comportamenti nettamente diversi.
+comportano dei comportamenti nettamente diversi.
La modalità preimpostata all'apertura del terminale è quella canonica, in cui
le operazioni di lettura vengono sempre effettuate assemblando i dati in una
editor ad esempio) che necessitano di poter leggere un carattere alla volta e
che gestiscono al loro interno i vari comandi.
-La struttura dell'I/O, come di solito viene gestito dal driver del terminale è
-mostrata in \secref{fig:term_struct}
+Per capire le caratteristiche dell'I/O sui terminali, occorre esaminare le
+modalità con cui esso viene effettuato; l'accesso, come per tutti i
+dispositivi, viene gestito da un driver apposito, la cui struttura generica è
+mostrata in \secref{fig:term_struct}. Ad un terminale sono sempre associate
+due code per gestire l'input e l'output, che ne implementano una
+bufferizzazione\footnote{completamente indipendente dalla eventuale ulteriore
+ bufferizzazione fornita dall'interfaccia standard dei file.} all'interno del
+kernel.
\begin{figure}[htb]
- \centering
- \includegraphics[width=13cm]{img/term_struct}
+ \centering \includegraphics[width=13cm]{img/term_struct}
\caption{Struttura interna generica di un driver per un terminale.}
\label{fig:term_struct}
\end{figure}
+La coda di ingresso mantiene i caratteri che sono stati letti dal terminale ma
+non ancora letti da un processo, la sua dimensione è definita dal parametro di
+sistema \macro{MAX\_INPUT} (si veda \secref{sec:sys_file_limits}), che ne
+specifica il limite minimo, in realtà la coda può essere più grande e cambiare
+dimensione dinamicamente. Se è stato abilitato il controllo di flusso in
+ingresso il driver emette i caratteri di STOP e START per bloccare e sbloccare
+l'ingresso dei dati; altrimenti i caratteri immessi oltre le dimensioni
+massime vengono persi; in alcuni casi il driver provvede ad inviare
+automaticamente un avviso (un carattere di BELL, che provoca un beep)
+sull'output quando si eccedono le dimensioni della coda. Se è abilitato il
+modo canonico i caratteri in ingresso restano nella coda fintanto che non
+viene ricevuto un a capo; un'altra parametro del sistema, \macro{MAX\_CANON},
+specifica la dimensione massima di una riga in modo canonico.
+
+La coda di uscita è analoga a quella di ingresso e contiene i caratteri
+scritti dai processi ma non ancora inviati al terminale. Se è abilitato il
+controllo di flusso in uscita il driver risponde ai caratteri di START e STOP
+inviati dal terminale. Le dimensioni della coda non sono specificate, ma non
+hanno molta importanza, in quanto qualora esse vengano eccedute il driver
+provvede automaticamente a bloccare la funzione chiamante.
+
+
+
+\subsection{La gestione delle caratteristiche di un terminale}
+\label{sec:term_attr}
+
+Data le loro peculiarità, fin dall'inizio si è posto il problema di come
+gestire le caratteristiche specifiche dei terminali; storicamente i vari
+dialetti di Unix hanno utilizzato diverse funzioni, alla fine con POSIX.1, è
+stata effettuata una standardizzazione, unificando le differenze fra BSD e
+System V in una unica interfaccia, che è quella usata dal Linux.
+
+Alcune di queste funzioni prendono come argomento un file descriptor (in
+origine molte operazioni venivano effettuate con \func{ioctl}), ma ovviamente
+possono essere usate solo con file che corrispondano effettivamente ad un
+terminale (altrimenti si otterrà un errore di \macro{ENOTTY}); questo può
+essere evitato utilizzando la funzione \func{isatty}, il cui prototipo è:
+\begin{prototype}{unistd.h}{int isatty(int desc)}
+
+ Controlla se il file descriptor \param{desc} è un terminale.
+
+\bodydesc{La funzione restituisce 1 se \param{desc} è connesso ad un
+ terminale, 0 altrimenti.}
+\end{prototype}
+
+Un'altra funzione che fornisce informazioni su un terminale è \func{ttyname},
+che permette di ottenere il nome del terminale associato ad un file
+descriptor; il suo prototipo è:
+\begin{prototype}{unistd.h}{char *ttyname(int desc)}
+
+ Restituisce il nome del terminale associato al file \param{desc}.
+
+ \bodydesc{La funzione restituisce il puntatore alla stringa contenente il
+ nome del terminale associato \param{desc} e \macro{NULL} in caso di
+ errore.}
+\end{prototype}
-L'I/O viene controllato attraverso una serie di attributi mantenuti per
-ciascun terminale in una struttura \var{termios}, i cui campi
+Si tenga presente che la funzione restituisce un indirizzo di dati statici,
+che pertanto possono essere sovrascritti da successive chiamate. Una funzione
+funzione analoga, anch'essa prevista da POSIX.1, è \func{ctermid}, il cui
+prototipo è:
+\begin{prototype}{stdio.h}{char *ctermid(char *s)}
+
+ Restituisce il nome del terminale di controllo del processo.
+
+ \bodydesc{La funzione restituisce il puntatore alla stringa contenente il
+ pathname del terminale.}
+\end{prototype}
+La funzione scrive il pathname del terminale di controllo del processo
+chiamante nella stringa posta all'indirizzo specificato dall'argomento
+\param{s}. La memoria per contenere la stringa deve essere stata allocata in
+precedenza ed essere lunga almeno
+\macro{L\_ctermid}\footnote{\macro{L\_ctermid} è una delle varie costanti del
+ sistema, non trattata esplicitamente in \secref{sec:sys_characteristics} che
+ indica la dimensione che deve avere una stringa per poter contenere il nome
+ di un terminale.} caratteri.
+
+Esiste infine una versione rientrante \func{ttyname\_r} della funzione
+\func{ttyname}, che non presenta il problema dell'uso di una zona di memoria
+statica; il suo prototipo è:
+\begin{prototype}{unistd.h}{int ttyname\_r(int desc, char *buff, size\_t len)}
+
+ Restituisce il nome del terminale associato al file \param{desc}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ errore, nel qual caso \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\macro{ERANGE}] la lunghezza del buffer, \param{len}, non è
+ sufficiente per contenere la stringa restituita.
+ \end{errlist}
+ ed inoltre \macro{EBADF} ed \macro{ENOSYS}.
+}
+\end{prototype}
+
+La funzione prende due argomenti, il puntatore alla zona di memoria
+\param{buff}, in cui l'utente vuole che il risultato venga scritto (dovrà
+ovviamente essere stata allocata in precedenza), e la relativa dimensione,
+\param{len}; se la stringa che deve essere restituita eccede questa dimensione
+si avrà una condizione di errore.
+
+Se si passa come argomento \macro{NULL} la funzione restituisce il puntatore
+ad una stringa statica che può essere sovrascritta da chiamate successive. Si
+tenga presente che il pathname restituito potrebbe non identificare
+univocamente il terminale (ad esempio potrebbe essere \file{/dev/tty}),
+inoltre non è detto che il processo possa effettivamente aprire il terminale.
+
+I vari attributi vengono mantenuti per ciascun terminale in una struttura
+\var{termios}, (la cui definizione è riportata in \figref{fig:term_termios}),
+usata dalle varie funzioni dell'interfaccia. In \figref{fig:term_termios} si
+sono riportati tutti i campi della definizione usata in Linux; di questi solo
+i primi cinque sono previsti dallo standard POSIX.1, ma le varie
+implementazioni ne aggiungono degli altri per mantenere ulteriori
+informazioni.\footnote{la definizione della struttura si trova in
+ \file{bits/termios.h}, da non includere mai direttamente, Linux, seguendo
+ l'esempio di BSD, aggiunge i due campi \var{c\_ispeed} e \var{c\_ospeed} per
+ mantenere le velocità delle linee seriali, ed un campo ulteriore,
+ \var{c\_line} per ... (NdT, trovare a che serve).}
-
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15cm}
tcflag_t c_oflag; /* output modes */
tcflag_t c_cflag; /* control modes */
tcflag_t c_lflag; /* local modes */
- cc_t c_cc[NCCS]; /* control chars */
-};
+ cc_t c_cc[NCCS]; /* control characters */
+ cc_t c_line; /* line discipline */
+ speed_t c_ispeed; /* input speed */
+ speed_t c_ospeed; /* output speed */
+;
\end{lstlisting}
\end{minipage}
\normalsize
\caption{La struttura \var{termios}, che identifica le proprietà di un
- terminale.}
+ terminale.}
\label{fig:term_termios}
\end{figure}
+I primi quattro campi sono quattro flag che controllano il comportamento del
+terminale; essi sono realizzati come maschera binaria, pertanto il tipo
+\type{tcflag\_t} è di norma realizzato con un intero senza segno di lunghezza
+opportuna. I valori devono essere specificati bit per bit, avendo cura di non
+modificare i bit su cui non si interviene.
+
+\begin{table}[b!ht]
+ \footnotesize
+ \centering
+ \begin{tabular}[c]{|l|p{11cm}|}
+ \hline
+ \textbf{Valore}& \textbf{Significato}\\
+ \hline
+ \hline
+ \macro{INPCK} & Abilita il controllo di parità in ingresso. Se non viene
+ impostato non viene fatto nessun controllo ed i caratteri
+ vengono passati in input direttamente.\\
+ \macro{IGNPAR} & Ignora gli errori di parità, il carattere viene passato
+ come ricevuto. Ha senso solo se si è impostato
+ \macro{INPCK}.\\
+ \macro{PARMRK} & Controlla come vengono riportati gli errori di parità. Ha
+ senso solo se \macro{INPCK} è impostato e \macro{IGNPAR}
+ no. Se impostato inserisce una sequenza \texttt{0xFF
+ 0x00} prima di ogni carattere che presenta errori di
+ parità, se non impostato un carattere con errori di
+ parità viene letto come uno \texttt{0x00}. Se un
+ carattere ha il valore \texttt{0xFF} e \macro{ISTRIP}
+ non è settato, per evitare ambiguità esso viene sempre
+ riportato come \texttt{0xFF 0xFF}.\\
+ \macro{ISTRIP} & Se impostato i caratteri in input sono tagliati a sette
+ bit mettendo a zero il bit più significativo, altrimenti
+ vengono passati tutti gli otto bit.\\
+ \macro{IGNBRK} & Ignora le condizioni di BREAK sull'input. Una
+ \textit{condizione di BREAK} è definita nel contesto di
+ una trasmissione seriale asincrona come una sequenza di
+ bit nulli più lunga di un byte. \\
+ \macro{BRKINT} & Controlla la reazione ad un BREAK quando
+ \macro{IGNBRK} non è impostato. Se \macro{BRKINT} è
+ impostato il BREAK causa lo scarico delle code,
+ e se il terminale è il terminale di controllo per un
+ gruppo in foreground anche l'invio di \macro{SIGINT} ai
+ processi di quest'ultimo. Se invece \macro{BRKINT} non è
+ impostato un BREAK viene letto come un carattere
+ NUL, a meno che non sia settato \macro{PARMRK}
+ nel qual caso viene letto come la sequenza di caratteri
+ \texttt{0xFF 0x00 0x00}.\\
+ \macro{IGNCR} & Se impostato il carattere di ritorno carrello
+ (\textit{carriage return}, \verb|'\r'|) viene scartato
+ dall'input. Può essere utile per i terminali che inviano
+ entrambi i caratteri di ritorno carrello e a capo
+ (\textit{newline}, \verb|'\n'|). \\
+ \macro{ICRNL} & Se impostato un carattere di ritorno carrello
+ (\verb|'\r'|) sul terminale viene automaticamente
+ trasformato in un a capo (\verb|'\n'|) sulla coda di
+ input. \\
+ \macro{INLCR} & Se impostato il carattere di a capo
+ (\verb|'\n'|) viene automaticamente trasformato in un
+ ritorno carrello (\verb|'\r'|).\\
+ \macro{IUCLC} & Se impostato trasforma i caratteri maiuscoli dal
+ terminale in minuscoli sull'ingresso (opzione non
+ POSIX).\\
+ \macro{IXON} & Se impostato attiva il controllo di flusso in uscita con i
+ caratteri di START e STOP. se si riceve
+ uno STOP l'output viene bloccato, e viene fatto
+ ripartire solo da uno START, e questi due
+ caratteri non vengono passati alla coda di input. Se non
+ impostato i due caratteri sono passati alla coda di input
+ insieme agli altri.\\
+ \macro{IXANY} & Se impostato con il controllo di flusso permette a
+ qualunque carattere di far ripartire l'output bloccato da
+ un carattere di STOP.\\
+ \macro{IXOFF} & Se impostato abilita il controllo di flusso in
+ ingresso. Il computer emette un carattere di STOP per
+ bloccare l'input dal terminale e lo sblocca con il
+ carattere START. \\
+ \macro{IMAXBEL}& Se impostato fa suonare il cicalino se si riempie la cosa
+ di ingresso; in Linux non è implementato e il kernel si
+ comporta cose se fosse sempre settato (è una estensione
+ BSD). \\
+ \hline
+ \end{tabular}
+ \caption{Costanti identificative dei vari bit del flag di controllo
+ \var{c\_iflag} delle modalità di input di un terminale.}
+ \label{tab:sess_termios_iflag}
+\end{table}
+
+Il primo flag, mantenuto nel campo \var{c\_iflag}, è detto \textsl{flag di
+ input} e controlla le modalità di funzionamento dell'input dei caratteri sul
+terminale, come il controllo di parità, il controllo di flusso, la gestione
+dei caratteri speciali; un elenco dei vari bit, del loro significato e delle
+costanti utilizzate per identificarli è riportato in
+\tabref{tab:sess_termios_iflag}.
+
+Si noti come alcuni di questi flag (come quelli per la gestione del flusso)
+fanno riferimento a delle caratteristiche che ormai sono completamente
+obsolete; la maggior parte inoltre è tipica di terminali seriali, e non ha
+alcun effetto su dispositivi diversi come le console virtuali o gli
+pseudo-terminali usati nelle connessioni di rete.
+
+\begin{table}[htb]
+ \footnotesize
+ \centering
+ \begin{tabular}[c]{|l|p{11cm}|}
+ \hline
+ \textbf{Valore}& \textbf{Significato}\\
+ \hline
+ \hline
+ \macro{OPOST} & Se impostato i caratteri vengono convertiti opportunamente
+ (in maniera dipendente dall'implementazione) per la
+ visualizzazione sul terminale, ad esempio al
+ carattere di a capo (NL) può venire aggiunto un ritorno
+ carrello (CR).\\
+ \macro{OCRNL} & Se impostato converte automaticamente il carattere di a
+ capo (NL) nella coppia di caratteri ritorno carrello, a
+ capo (CR-NL).\\
+ \macro{OLCUC} & Se impostato trasforma i caratteri minuscoli in ingresso
+ in caratteri maiuscoli sull'uscita (non previsto da
+ POSIX.1).\\
+ \macro{ONLCR} & Se impostato converte automaticamente il carattere di a
+ capo (NL) in un carattere di ritorno carrello (CR).\\
+ \macro{ONOCR} & Se impostato converte il carattere di ritorno carrello
+ (CR) nella coppia di caratteri CR-NL.\\
+ \macro{ONLRET}& Se impostato rimuove dall'output il carattere di ritorno
+ carrello (CR).\\
+ \macro{OFILL} & Se impostato in caso di ritardo sulla linea invia dei
+ caratteri di riempimento invece di attendere.\\
+ \macro{OFDEL} & Se impostato il carattere di riempimento è DEL
+ (\texttt{0x3F}), invece che NUL (\texttt{0x00}).\\
+ \macro{NLDLY} & Maschera per i bit che indicano il ritardo per il
+ carattere di a capo (NL), i valori possibili sono
+ \macro{NL0} o \macro{NL1}.\\
+ \macro{CRDLY} & Maschera per i bit che indicano il ritardo per il
+ carattere ritorno carrello (CR), i valori possibili sono
+ \macro{CR0}, \macro{CR1}, \macro{CR2} o \macro{CR3}.\\
+ \macro{TABDLY}& Maschera per i bit che indicano il ritardo per il
+ carattere di tabulazione, i valori possibili sono
+ \macro{TAB0}, \macro{TAB1}, \macro{TAB2} o \macro{TAB3}.\\
+ \macro{BSDLY} & Maschera per i bit che indicano il ritardo per il
+ carattere di ritorno indietro (\textit{backspace}), i
+ valori possibili sono \macro{BS0} o \macro{BS1}.\\
+ \macro{VTDLY} & Maschera per i bit che indicano il ritardo per il
+ carattere di tabulazione verticale, i valori possibili sono
+ \macro{VT0} o \macro{VT1}.\\
+ \macro{FFDLY} & Maschera per i bit che indicano il ritardo per il
+ carattere di pagina nuova (\textit{form feed}), i valori
+ possibili sono \macro{FF0} o \macro{FF1}.\\
+ \hline
+ \end{tabular}
+ \caption{Costanti identificative dei vari bit del flag di controllo
+ \var{c\_oflag} delle modalità di output di un terminale.}
+ \label{tab:sess_termios_oflag}
+\end{table}
+
+Il secondo flag, mantenuto nel campo \var{c\_oflag}, è detto \textsl{flag di
+ output} e controlla le modalità di funzionamento dell'output dei caratteri,
+come l'impacchettamento dei caratteri sullo schermo, la traslazione degli a
+capo, la conversione dei caratteri speciali; un elenco dei vari bit, del loro
+significato e delle costanti utilizzate per identificarli è riportato in
+\tabref{tab:sess_termios_oflag}.
+
+Si noti come alcuni dei valori riportati in \tabref{tab:sess_termios_oflag}
+fanno riferimento a delle maschere di bit; essi infatti vengono utilizzati per
+impostare alcuni valori numerici relativi ai ritardi nell'output di alcuni
+caratteri: una caratteristica originaria dei primi terminali su telescrivente,
+che avevano bisogno di tempistiche diverse per spostare il carrello in
+risposta ai caratteri speciali, e che oggi sono completamente in disuso.
+
+Si tenga presente inoltre che nel caso delle maschere il valore da inserire in
+\var{c\_oflag} deve essere fornito avendo cura di cancellare prima tutti i bit
+della maschera, i valori da immettere infatti (quelli riportati nella
+spiegazione corrispondente) sono numerici e non per bit, per cui possono
+sovrapporsi fra di loro. Occorrerà perciò utilizzare un codice del tipo:
+
+\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}%
+ c_oflag &= (~CRDLY);
+ c_oflag |= CR1;
+\end{lstlisting}
+
+\noindent che prima cancella i bit della maschera in questione e poi setta il
+valore.
+
+
+\begin{table}[htb]
+ \footnotesize
+ \centering
+ \begin{tabular}[c]{|l|p{11cm}|}
+ \hline
+ \textbf{Valore}& \textbf{Significato}\\
+ \hline
+ \hline
+ \macro{CLOCAL} & Se impostato indica che il terminale è connesso in locale
+ e che le linee di controllo del modem devono essere
+ ignorate. Se non impostato effettuando una chiamata ad
+ \func{open} senza aver specificato il flag di
+ \macro{O\_NOBLOCK} si bloccherà il processo finché
+ non si è stabilita una connessione con il modem; inoltre
+ se viene rilevata una disconessione viene inviato un
+ \macro{SIGHUP} al processo di controllo del terminale. La
+ lettura su un terminale sconnesso comporta una condizione
+ di \textit{end of file} e la scrittura un errore di
+ \macro{EIO}. \\
+ \macro{HUPCL} & Se è impostato viene distaccata la connessione del
+ modem quando l'ultimo dei processi che ha ancora un file
+ aperto sul terminale lo chiude o esce.\\
+ \macro{CREAD} & Se è impostato si può leggere l'input del terminale,
+ altrimenti i caratteri in ingresso vengono scartati
+ quando arrivano.\\
+ \macro{CSTOPB} & Se impostato vengono usati due bit di stop sulla linea
+ seriale, se non impostato ne viene usato soltanto uno.\\
+ \macro{PARENB} & Se impostato abilita la generazione il controllo di
+ parità. La reazione in caso di errori dipende dai
+ relativi valori per \var{c\_iflag}, riportati in
+ \tabref{tab:sess_termios_iflag}. Se non è impostato i bit
+ di parità non vengono
+ generati e i caratteri non vengono controllati.\\
+ \macro{PARODD} & Ha senso solo se è attivo anche \macro{PARENB}. Se
+ impostato viene usata una parità è dispari, altrimenti
+ viene usata una parità pari.\\
+ \macro{CSIZE} & Maschera per i bit usati per specificare la dimensione
+ del carattere inviato lungo la linea di trasmissione, i
+ valore ne indica la lunghezza (in bit), ed i valori
+ possibili sono \macro{CS5}, \macro{CS6},
+ \macro{CS7} e \macro{CS8}
+ corrispondenti ad un analogo numero di bit.\\
+ \macro{CBAUD} & Maschera dei bit (4+1) usati per impostare della velocità
+ della linea (il \textit{baud rate}) in ingresso.
+ In Linux non è implementato in quanto viene
+ usato un apposito campo di \var{termios}.\\
+ \macro{CBAUDEX}& Bit aggiuntivo per l'impostazione della velocità della
+ linea, per le stesse motivazioni del precedente non è
+ implementato in Linux.\\
+ \macro{CIBAUD} & Maschera dei bit della velocità della linea in
+ ingresso. Analogo a \macro{CBAUD}, anch'esso in Linux è
+ mantenuto in un apposito campo di \var{termios}. \\
+ \macro{CRTSCTS}& Abilita il controllo di flusso hardware sulla seriale,
+ attraverso l'utilizzo delle dei due fili di RTS e CTS.\\
+ \hline
+ \end{tabular}
+ \caption{Costanti identificative dei vari bit del flag di controllo
+ \var{c\_cflag} delle modalità di controllo di un terminale.}
+ \label{tab:sess_termios_cflag}
+\end{table}
+
+Il terzo flag, mantenuto nel campo \var{c\_cflag}, è detto \textsl{flag di
+ controllo} ed è legato al funzionamento delle linee seriali, permettendo di
+impostarne varie caratteristiche, come il numero di bit di stop, i settaggi
+della parità, il funzionamento del controllo di flusso; esso ha senso solo per
+i terminali connessi a linee seriali. Un elenco dei vari bit, del loro
+significato e delle costanti utilizzate per identificarli è riportato in
+\tabref{tab:sess_termios_cflag}.
+
+I valori di questo flag sono molto specifici, e completamente indirizzati al
+controllo di un terminale mantenuto su una linea seriale; essi pertanto non
+hanno nessuna rilevanza per i terminali che usano un'altra interfaccia, come
+le console virtuali e gli pseudo-terminali usati dalle connessioni di rete.
+
+Inoltre alcuni valori sono previsti solo per quelle implementazioni (lo
+standard POSIX non specifica nulla riguardo l'implementazione, ma solo delle
+funzioni di lettura e scrittura) che mantengono le velocità delle linee
+seriali all'interno dei flag; come accennato in Linux questo viene fatto
+(seguendo l'esempio di BSD) attraverso due campi aggiuntivi, \var{c\_ispeed} e
+\var{c\_ospeed}, nella struttura \var{termios} (mostrati in
+\figref{fig:term_termios}).
+
+\begin{table}[b!ht]
+ \footnotesize
+ \centering
+ \begin{tabular}[c]{|l|p{11cm}|}
+ \hline
+ \textbf{Valore}& \textbf{Significato}\\
+ \hline
+ \hline
+ \macro{ICANON} & Se impostato il terminale opera in modo canonico,
+ altrimenti opera in modo non canonico.\\
+ \macro{ECHO} & Se è impostato viene attivato l'eco dei caratteri in
+ input sull'output del terminale.\\
+ \macro{ECHOE} & Se è impostato l'eco mostra la cancellazione di un
+ carattere in input (in reazione al carattere ERASE)
+ cancellando l'ultimo carattere della riga corrente dallo
+ schermo; altrimenti il carattere è rimandato in eco per
+ mostrare quanto accaduto (usato per i terminali con
+ l'uscita su una stampante). \\
+ \macro{ECHOPRT}& Se impostato abilita la visualizzazione del carattere di
+ cancellazione in una modalità adatta ai terminali con
+ l'uscita su stampante; l'invio del carattere di ERASE
+ comporta la stampa di un \verb|\| seguito dal carattere
+ cancellato, e così via in caso di successive
+ cancellazioni, quando si riprende ad immettere carattere
+ normali prima verrà stampata una \texttt{/}.\\
+ \macro{ECHOK} & Se impostato abilita il trattamento della visualizzazione
+ del carattere KILL, andando a capo dopo aver visualizzato
+ lo stesso, altrimenti viene solo mostrato il carattere e
+ sta all'utente ricordare che l'input precedente è stato
+ cancellato. \\
+ \macro{ECHOKE} & Se impostato abilita il trattamento della visualizzazione
+ del carattere KILL cancellando i caratteri precedenti
+ nella linea secondo le modalità specificate dai valori di
+ \macro{ECHOE} e \macro{ECHOPRT}.\\
+ \macro{ECHONL} & Se impostato viene effettuato l'eco di un a
+ capo (\verb|\n|) anche se non è stato impostato
+ \macro{ECHO}. \\
+ \macro{ECHOCTL}& Se impostato insieme ad \macro{ECHO} i caratteri di
+ controllo ASCII (tranne TAB, NL, START, e STOP) sono
+ mostrati nella forma che prepende un \verb|^| alla
+ lettera ottenuta sommando \texttt{0x40} al valore del
+ carattere (di solito questi si possono ottenere anche
+ direttamente premendo il tasto \texttt{ctrl} più la
+ relativa lettera).\\
+ \macro{ISIG} & Se impostato abilita il riconoscimento dei caratteri
+ INTR, QUIT, e SUSP generando il relativo segnale.\\
+ \macro{IEXTEN} & Abilita alcune estensioni previste dalla
+ implementazione. Deve essere impostato perché caratteri
+ speciali come EOL2, LNEXT, REPRINT e WERASE possano
+ essere interpretati. \\
+ \macro{NOFLSH} & Se impostato disabilita lo scarico delle code di ingresso
+ e uscita quando vengono emessi i segnali \macro{SIGINT},
+ \macro{SIGQUIT} and \macro{SIGSUSP}.\\
+ \macro{TOSTOP} & Se abilitato, con il supporto per il job control presente,
+ genera il segnale \macro{SIGTTOU} per un processo in
+ background che cerca di scrivere sul terminale.\\
+ \macro{XCASE} & Se settato il terminale funziona solo con le
+ maiuscole. L'input è convertito in minuscole tranne per i
+ caratteri preceduti da una \verb|\|. In output le
+ maiuscole sono precedute da una \verb|\| e le minuscole
+ convertite in maiuscole.\\
+ \macro{DEFECHO}& Se impostate effettua l'eco solo se c'è un processo in
+ lettura.\\
+ \macro{FLUSHO} & Effettua la cancellazione della coda di uscita. Viene
+ attivato dal carattere DISCARD. Non è supportato in
+ Linux.\\
+ \macro{PENDIN} & Indica che la linea deve essere ristampata, viene
+ attivato dal carattere REPRINT e resta attivo fino alla
+ fine della ristampa. Non è supportato in Linux.\\
+ \hline
+ \end{tabular}
+ \caption{Costanti identificative dei vari bit del flag di controllo
+ \var{c\_lflag} delle modalità locali di un terminale.}
+ \label{tab:sess_termios_lflag}
+\end{table}
+
+Il quarto flag, mantenuto nel campo \var{c\_lflag}, è detto \textsl{flag
+ locale}, e serve per controllare il funzionamento dell'interfaccia fra il
+driver e l'utente, come abilitare l'eco, gestire i caratteri di controllo e
+l'emissione dei segnali, impostare modo canonico o non canonico; un elenco dei
+vari bit, del loro significato e delle costanti utilizzate per identificarli è
+riportato in \tabref{tab:sess_termios_lflag}. Con i terminali odierni l'unico
+flag con cui probabilmente si può avere a che fare è questo, in quanto è con
+questo che si impostano le caratteristiche generiche comuni a tutti i
+terminali.
+
+Si tenga presente che i flag che riguardano le modalità di eco dei caratteri
+(\macro{ECHOE}, \macro{ECHOPRT}, \macro{ECHOK}, \macro{ECHOKE},
+\macro{ECHONL}) controllano solo il comportamento della visualizzazione, il
+riconoscimento dei vari caratteri dipende dalla modalità di operazione, ed
+avviene solo in modo canonico, pertanto questi flag non hanno significato se
+non è impostato \macro{ICANON}.
+
+Oltre ai vari flag per gestire le varie caratteristiche dei terminali,
+\var{termios} contiene pure il campo \var{c\_cc} che viene usato per impostare
+i caratteri speciali associati alle varie funzioni di controllo. Il numero di
+questi caratteri speciali è indicato dalla costante \macro{NCCS}, POSIX ne
+specifica almeno 11, ma molte implementazioni ne definiscono molti
+altri.\footnote{in Linux il valore della costante è 32, anche se i caratteri
+ effettivamente definiti sono solo 17.}
+
+\begin{table}[htb]
+ \footnotesize
+ \centering
+ \begin{tabular}[c]{|l|c|c|p{8cm}|}
+ \hline
+ \textbf{Indice} & \textbf{Valore}&\textbf{Codice} & \textbf{Funzione}\\
+ \hline
+ \hline
+ \macro{VINTR} &\texttt{0x03}&(\verb|C-c|)& Carattere di interrupt,
+ provoca l'emissione di
+ \macro{SIGINT}. \\
+ \macro{VQUIT} &\texttt{0x1C}&(\verb|C-\|)& Carattere di uscita provoca
+ l'emissione di
+ \macro{SIGQUIT}.\\
+ \macro{VERASE} &\texttt{0x7f}& DEL & Carattere di ERASE, cancella
+ l'ultimo carattere precedente
+ nella linea.\\
+ \macro{VKILL} &\texttt{0x15}&(\verb|C-u|)& Carattere di KILL, cancella
+ l'intera riga.\\
+ \macro{VEOF} &\texttt{0x04}&(\verb|C-d|)& Carattere di
+ \textit{end-of-file}. Causa
+ l'invio del contenuto del
+ buffer di ingresso al
+ processo in lettura anche se
+ non è ancora stato ricevuto
+ un a capo. Se è il primo
+ carattere immesso comporta il
+ ritorno di \func{read} con
+ zero caratteri, cioè la
+ condizione di
+ \textit{end-of-file}.\\
+ \macro{VTIME} & --- & --- & Timeout, in decimi di secondo, per
+ una lettura in modo non canonico. \\
+ \macro{VMIN} & --- & --- & Numero minimo di caratteri per una
+ lettura in modo non canonico.\\
+ \macro{VSWTC} &\texttt{0x00}& NUL & Carattere di switch. Non supportato
+ in Linux.\\
+ \macro{VSTART} &\texttt{0x21}&(\verb|C-q|)& Carattere di START. Riavvia un
+ output bloccato da uno STOP.\\
+ \macro{VSTOP} &\texttt{0x23}&(\verb|C-s|)& Carattere di STOP. Blocca
+ l'output fintanto che non
+ viene premuto un carattere di
+ START.\\
+ \macro{VSUSP} &\texttt{0x1A}&(\verb|C-z|)& Carattere di
+ sospensione. Invia il segnale
+ \macro{SIGTSTP}.\\
+ \macro{VEOL} &\texttt{0x00}& NUL & Carattere di fine riga. Agisce come
+ un a capo, ma non viene scartato ed
+ è letto come l'ultimo carattere
+ nella riga. \\
+ \macro{VREPRINT}&\texttt{0x12}&(\verb|C-r|)& Ristampa i caratteri non
+ ancora letti. \\
+ \macro{VDISCARD}&\texttt{0x07}&(\verb|C-o|)& Non riconosciuto in Linux. \\
+ \macro{VWERASE} &\texttt{0x17}&(\verb|C-w|)& Cancellazione di una parola.\\
+ \macro{VLNEXT} &\texttt{0x16}&(\verb|C-v|)& Carattere di escape, serve a
+ quotare il carattere
+ successivo che non viene
+ interpretato ma passato
+ direttamente all'output. \\
+ \macro{VEOL2} &\texttt{0x00}& NUL & Ulteriore carattere di fine
+ riga. Ha lo stesso effetto di
+ \macro{VEOL} ma può essere un
+ carattere diverso. \\
+ \hline
+ \end{tabular}
+ \caption{Valori dei caratteri di controllo mantenuti nel campo \var{c\_cc}
+ della struttura \var{termios}.}
+ \label{tab:sess_termios_cc}
+\end{table}
+
+
+A ciascuna di queste funzioni di controllo corrisponde un elemento del vettore
+\var{c\_cc} che specifica quale è il carattere speciale associato; per
+portabilità invece di essere indicati con la loro posizione numerica nel
+vettore, i vari elementi vengono indicizzati attraverso delle opportune
+costanti, il cui nome corrisponde all'azione ad essi associata. Un elenco
+completo dei caratteri di controllo, con le costanti e delle funzionalità
+associate è riportato in \tabref{tab:sess_termios_cc}, usando quelle
+definizioni diventa possibile assegnare un nuovo carattere di controllo con un
+codice del tipo:
+\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}%
+ value.c_cc[VEOL2] = '\n';
+\end{lstlisting}
+
+La maggior parte di questi caratteri (tutti tranne \macro{VTIME} e
+\macro{VMIN}) hanno effetto solo quando il terminale viene utilizzato in modo
+canonico; per alcuni devono essere essere soddisfatte ulteriori richieste, ad
+esempio \macro{VINTR}, \macro{VSUSP}, e \macro{VQUIT} richiedono sia settato
+\macro{ISIG}; \macro{VSTART} e \macro{VSTOP} richiedono sia settato
+\macro{IXON}; \macro{VLNEXT}, \macro{VWERASE}, \macro{VREPRINT} richiedono sia
+settato \macro{IEXTEN}. In ogni caso quando vengono attivati i caratteri
+vengono interpretati e non sono passati sulla coda di ingresso.
+
+Per leggere ed scrivere tutte le impostazioni dei terminali lo standard POSIX
+prevede due funzioni, \func{tcgetattr} e \func{tcsetattr}; entrambe utilizzano
+come argomento un puntatore ad struttura \var{termios} che sarà quella in cui
+andranno immagazzinate le impostazioni, il loro prototipo è:
+\begin{functions}
+ \headdecl{unistd.h}
+ \headdecl{termios.h}
+ \funcdecl{int tcgetattr(int fd, struct termios *termios\_p)}
+ Legge il valore delle impostazioni di un terminale.
+
+ \funcdecl{int tcsetattr(int fd, int optional\_actions, struct termios
+ *termios\_p)}
+ Scrive le impostazioni di un terminale.
+
+ \bodydesc{Entrambe le funzioni restituiscono 0 in caso di successo e -1 in
+ caso di errore, nel qual caso \var{errno} assumerà i valori:
+ \begin{errlist}
+ \item[\macro{EINTR}] La funzione è stata interrotta.
+ \end{errlist}
+ ed inoltre \macro{EBADF}, \macro{ENOTTY} ed \macro{EINVAL}.
+ }
+\end{functions}
+
+Le funzioni operano sul terminale cui fa riferimento il file descriptor
+\param{fd} utilizzando la struttura indicata dal puntatore \param{termios\_p}
+per lo scambio dei dati. Si tenga presente che le impostazioni sono associate
+al terminale e non al file descriptor; questo significa che se si è cambiata
+una impostazione un qualunque altro processo che apra lo stesso terminale, od
+un qualunque altro file descriptor che vi faccia riferimento, vedrà le nuove
+impostazioni pur non avendo nulla a che fare con il file descriptor che si è
+usato per effettuare i cambiamenti.
+
+Questo significa che non è possibile usare file descriptor diversi per
+utilizzare automaticamente il terminale in modalità diverse, se esiste una
+necessità di accesso differenziato di questo tipo occorrerà cambiare
+esplicitamente la modalità tutte le volte che si passa da un file descriptor
+ad un altro.
+
+La funzione \func{tcgetattr} legge i valori correnti delle impostazioni di un
+terminale qualunque nella struttura puntata da \param{termios\_p};
+\func{tcsetattr} invece effettua la scrittura delle impostazioni e quando
+viene invocata sul proprio terminale di controllo può essere eseguita con
+successo solo da un processo in foreground. Se invocata da un processo in
+background infatti tutto il gruppo riceverà un segnale di \macro{SIGTTOU} come
+se si fosse tentata una scrittura, a meno che il processo chiamante non abbia
+\macro{SIGTTOU} ignorato o bloccato, nel qual caso l'operazione sarà eseguita.
+
+La funzione \func{tcsetattr} prevede tre diverse modalità di funzionamento,
+specificabili attraverso l'argomento \param{optional\_actions}, che permette
+di stabilire come viene eseguito il cambiamento delle impostazioni del
+terminale, i valori possibili sono riportati in
+\tabref{tab:sess_tcsetattr_option}; di norma (come fatto per le due funzioni
+di esempio) si usa sempre \macro{TCSANOW}, le altre opzioni possono essere
+utili qualora si cambino i parametri di output.
+
+\begin{table}[htb]
+ \footnotesize
+ \centering
+ \begin{tabular}[c]{|l|p{8cm}|}
+ \hline
+ \textbf{Valore}& \textbf{Significato}\\
+ \hline
+ \hline
+ \macro{TCSANOW} & Esegue i cambiamenti in maniera immediata. \\
+ \macro{TCSADRAIN}& I cambiamenti vengono eseguiti dopo aver atteso che
+ tutto l'output presente sulle code è stato scritto. \\
+ \macro{TCSAFLUSH}& È identico a \macro{TCSADRAIN}, ma in più scarta
+ tutti i dati presenti sulla coda di input.\\
+ \hline
+ \end{tabular}
+ \caption{Possibili valori per l'argomento \param{optional\_actions} della
+ funzione \func{tcsetattr}.}
+ \label{tab:sess_tcsetattr_option}
+\end{table}
+
+Occorre infine tenere presente che \func{tcsetattr} ritorna con successo anche
+se soltanto uno dei cambiamenti richiesti è stato eseguito. Pertanto se si
+effettuano più cambiamenti è buona norma controllare con una ulteriore
+chiamata a \func{tcgetattr} che essi siano stati eseguiti tutti quanti.
+
+\begin{figure}[!htb]
+ \footnotesize
+ \begin{lstlisting}{}%
+#include <unistd.h>
+#include <termios.h>
+#include <errno.h>
+
+int SetTermAttr(int fd, tcflag_t flag)
+{
+ struct termios values;
+ int res;
+ res = tcgetattr (desc, &values);
+ if (res) {
+ perror("Cannot get attributes");
+ return res;
+ }
+ values.c_lflag |= flag;
+ res = tcsetattr (desc, TCSANOW, &values);
+ if (res) {
+ perror("Cannot set attributes");
+ return res;
+ }
+ return 0;
+}
+ \end{lstlisting}
+ \caption{Codice della funzione \func{SetTermAttr} che permette di
+ impostare uno dei flag di controllo locale del terminale.}
+ \label{fig:term_set_attr}
+\end{figure}
+
+Come già accennato per i cambiamenti effettuati ai vari flag di controllo
+occorre che i valori di ciascun bit siano specificati avendo cura di mantenere
+intatti gli altri; per questo motivo in generale si deve prima leggere il
+valore corrente delle impostazioni con \func{tcgetattr} per poi modificare i
+valori impostati.
+
+In \figref{fig:term_set_attr} e \figref{fig:term_unset_attr} si è riportato
+rispettivamente il codice delle due funzioni \func{SetTermAttr} e
+\func{UnSetTermAttr}, che possono essere usate per impostare o rimuovere, con
+le dovute precauzioni, un qualunque bit di \var{c\_lflag}. Il codice di
+entrambe le funzioni può essere trovato nel file \file{SetTermAttr.c} dei
+sorgenti allegati.
+
+La funzione \func{SetTermAttr} provvede ad impostare il bit specificato
+dall'argomento \param{flag}; prima si leggono i valori correnti
+(\texttt{\small 10}) con \func{tcgetattr}, uscendo con un messaggio in caso di
+errore (\texttt{\small 11--14}), poi si provvede a impostare solo i bit
+richiesti (possono essere più di uno) con un OR binario (\texttt{\small 15});
+infine si scrive il nuovo valore modificato con \func{tcsetattr}
+(\texttt{\small 16}), notificando un eventuale errore (\texttt{\small 11--14})
+o uscendo normalmente.
+
+\begin{figure}[!htb]
+ \footnotesize
+ \begin{lstlisting}{}%
+int UnSetTermAttr(int fd, tcflag_t flag)
+{
+ struct termios values;
+ int res;
+ res = tcgetattr (desc, &values);
+ if (res) {
+ perror("Cannot get attributes");
+ return res;
+ }
+ values.c_lflag &= (~flag);
+ res = tcsetattr (desc, TCSANOW, &values);
+ if (res) {
+ perror("Cannot set attributes");
+ return res;
+ }
+ return 0;
+}
+ \end{lstlisting}
+ \caption{Codice della funzione \func{UnSetTermAttr} che permette di
+ rimuovere uno dei flag di controllo locale del terminale.}
+ \label{fig:term_unset_attr}
+\end{figure}
+
+La seconda funzione, \func{UnSetTermAttr}, è assolutamente identica alla
+prima, solo che in questo caso (in \texttt{\small 15}) si rimuovono i bit
+specificati dall'argomento \param{flag} usando un AND binario del valore
+negato.
+
+
+Al contrario di tutte le altre caratteristiche dei terminali, che possono
+essere impostate esplicitamente utilizzando gli opportuni campi di
+\var{termios}, per le velocità della linea (il cosiddetto \textit{baud rate})
+non è prevista una implementazione standardizzata, per cui anche se in Linux
+sono mantenute in due campi dedicati nella struttura, questi non devono essere
+acceduti direttamente ma solo attraverso le apposite funzioni di interfaccia
+provviste da POSIX.1.
+
+Lo standard prevede due funzioni per scrivere la velocità delle linee seriali,
+\func{cfsetispeed} per la velocità della linea di ingresso e
+\func{cfsetospeed} per la velocità della linea di uscita; i loro prototipi
+sono:
+\begin{functions}
+ \headdecl{unistd.h}
+ \headdecl{termios.h}
+ \funcdecl{int cfsetispeed(struct termios *termios\_p, speed\_t speed)}
+ Imposta la velocità delle linee seriali in ingresso.
+
+ \funcdecl{int cfsetospeed(struct termios *termios\_p, speed\_t speed)}
+ Imposta la velocità delle linee seriali in uscita.
+
+ \bodydesc{Entrambe le funzioni restituiscono 0 in caso di successo e -1 in
+ caso di errore, che avviene solo quando il valore specificato non è
+ valido.}
+\end{functions}
+
+Si noti che le funzioni si limitano a scrivere opportunamente il valore della
+velocità prescelta \var{speed} all'interno della struttura puntata da
+\var{termios\_p}; per effettuare l'impostazione effettiva occorrerà poi
+chiamare \func{tcsetattr}.
+
+Si tenga presente che per le linee seriali solo alcuni valori di velocità sono
+validi; questi possono essere specificati direttamente (le \acr{glibc}
+prevedono che i valori siano indicati in bit per secondo), ma in generale
+altre versioni di librerie possono utilizzare dei valori diversi; per questo
+POSIX.1 prevede una serie di costanti che però servono solo per specificare le
+velocità tipiche delle linee seriali:
+\begin{verbatim}
+ B0 B50 B75 B110 B134 B150
+ B200 B300 B600 B1200 B1800 B2400
+ B4800 B9600 B19200 B38400 B57600 B115200
+ B230400 B460800
+\end{verbatim}
+
+Un terminale può utilizzare solo alcune delle velocità possibili, le funzioni
+però non controllano se il valore specificato è valido, dato che non possono
+sapere a quale terminale le velocità saranno applicate; sarà l'esecuzione di
+\func{tcsetattr} a fallire quando si cercherà di eseguire l'impostazione.
+
+Di norma il valore ha senso solo per i terminali seriali dove indica appunto
+la velocità della linea di trasmissione; se questa non corrisponde a quella
+del terminale quest'ultimo non potrà funzionare: quando il terminale non è
+seriale il valore non influisce sulla velocità di trasmissione dei dati.
+
+In generale impostare un valore nullo (\macro{B0}) sulla linea di output fa si
+che il modem non asserisca più le linee di controllo, interrompendo di fatto
+la connessione, qualora invece si utilizzi questo valore per la linea di input
+l'effetto sarà quello di rendere la sua velocità identica a quella della linea
+di output.
+
+Analogamente a quanto avviene per l'impostazione, le velocità possono essere
+lette da una struttura \var{termios} utilizzando altre due funzioni,
+\func{cfgetispeed} e \func{cfgetospeed}, i cui prototipi sono:
+\begin{functions}
+ \headdecl{unistd.h}
+ \headdecl{termios.h}
+ \funcdecl{speed\_t cfgetispeed(struct termios *termios\_p)}
+ Legge la velocità delle linee seriali in ingresso.
+
+ \funcdecl{speed\_t cfgetospeed(struct termios *termios\_p)}
+ Legge la velocità delle linee seriali in uscita.
+
+ \bodydesc{Entrambe le funzioni restituiscono la velocità della linea, non
+ sono previste condizioni di errore.}
+\end{functions}
+
+Anche in questo caso le due funzioni estraggono i valori della velocità della
+linea da una struttura, il cui indirizzo è specificato dall'argomento
+\param{termios\_p} che deve essere stata letta in precedenza con
+\func{tcgetaddr}.
+
+
+\subsection{La gestione della disciplina di linea.}
+\label{sec:term_line_discipline}
-\subsection{Il \textsl{modo canonico}}
-\label{sec:term_canonic_mode}
+Come illustrato dalla struttura riportata in \figref{fig:term_struct} tutti i
+terminali hanno un insieme di funzionalità comuni, che prevedono la presenza
+di code di ingresso ed uscita; in generale si fa riferimento ad esse con il
+nome di \textsl{discipline di linea}.
-Il modo canonico
+Lo standard POSIX prevede alcune funzioni che permettono di intervenire
+direttamente sulla gestione di quest'ultime e sull'interazione fra i dati in
+ingresso ed uscita e le relative code. In generale tutte queste funzioni
+vengono considerate, dal punto di vista dell'accesso al terminale, come delle
+funzioni di scrittura, pertanto se usate da processi in background sul loro
+terminale di controllo provocano l'emissione di \macro{SIGTTOU} come
+illustrato in \secref{sec:sess_ctrl_term}.\footnote{con la stessa eccezione,
+ già vista per \func{tcsetaddr}, che quest'ultimo sia bloccato o ignorato dal
+ processo chiamante.}
-\subsection{Il \textsl{modo non canonico}}
-\label{sec:term_noncanonic_mode}
+Una prima funzione, che è efficace solo in caso di terminali seriali asincroni
+(non fa niente per tutti gli altri terminali), è \func{tcsendbreak}; il suo
+prototipo è:
+\begin{functions}
+ \headdecl{unistd.h}
+ \headdecl{termios.h}
+
+ \funcdecl{int tcsendbreak(int fd, int duration)} Genera una condizione di
+ break inviando un flusso di bit nulli.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ errore, nel qual caso \var{errno} assumerà i valori \macro{EBADF} o
+ \macro{ENOTTY}.}
+\end{functions}
+
+La funzione invia un flusso di bit nulli (che genera una condizione di break)
+sul terminale associato a \param{fd}; un valore nullo di \param{duration}
+implica una durata del flusso fra 0.25 e 0.5 secondi, un valore diverso da
+zero implica una durata pari a \code{duration*T} dove \code{T} è un valore
+compreso fra 0.25 e 0.5.\footnote{POSIX specifica il comportamento solo nel
+ caso si sia impostato un valore nullo per \param{duration}; il comportamento
+ negli altri casi può dipendere dalla implementazione.}
+
+Le altre funzioni previste da POSIX servono a controllare il comportamento
+dell'interazione fra le code associate al terminale e l'utente; la prima è
+\func{tcdrain}, il cui prototipo è:
+\begin{functions}
+ \headdecl{unistd.h}
+ \headdecl{termios.h}
+
+ \funcdecl{int tcdrain(int fd)} Attende lo svuotamento della coda di output.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ errore, nel qual caso \var{errno} assumerà i valori \macro{EBADF} o
+ \macro{ENOTTY}.}
+\end{functions}
+
+La funzione blocca il processo fino a che tutto l'output presente sulla coda
+di uscita non è stato trasmesso al terminale associato ad \param{fd}. % La
+ % funzione è un punto di cancellazione per i
+ % programmi multi-thread, in tal caso le
+ % chiamate devono essere protette con dei
+ % gestori di cancellazione.
+
+Una seconda funzione, \func{tcflush}, permette svuotare immediatamente le code
+di cancellando tutti i dati presenti al loro interno; il suo prototipo è:
+\begin{functions}
+ \headdecl{unistd.h} \headdecl{termios.h}
+
+ \funcdecl{int tcflush(int fd, int queue)} Cancella i dati presenti
+ nelle code di ingresso o di uscita.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ errore, nel qual caso \var{errno} assumerà i valori \macro{EBADF} o
+ \macro{ENOTTY}.}
+\end{functions}
+
+La funzione agisce sul terminale associato a \param{fd}, l'argomento
+\param{queue} permette di specificare su quale coda (ingresso, uscita o
+entrambe), operare. Esso può prendere i valori riportati in
+\tabref{tab:sess_tcflush_queue}, nel caso si specifichi la coda di ingresso
+cancellerà i dati ricevuti ma non ancora letti, nel caso si specifichi la coda
+di uscita cancellerài dati scritti ma non ancora trasmessi.
+
+\begin{table}[htb]
+ \footnotesize
+ \centering
+ \begin{tabular}[c]{|l|p{8cm}|}
+ \hline
+ \textbf{Valore}& \textbf{Significato}\\
+ \hline
+ \hline
+ \macro{TCIFLUSH} & Cancella i dati sulla coda di ingresso. \\
+ \macro{TCOFLUSH} & Cancella i dati sulla coda di uscita. \\
+ \macro{TCIOFLUSH}& Cancella i dati su entrambe le code.\\
+ \hline
+ \end{tabular}
+ \caption{Possibili valori per l'argomento \param{queue} della
+ funzione \func{tcflush}.}
+ \label{tab:sess_tcflush_queue}
+\end{table}
+
+
+L'ultima funzione dell'interfaccia che interviene sulla disciplina di linea è
+\func{tcflow}, che viene usata per sospendere la trasmissione e la ricezione
+dei dati sul terminale; il suo prototipo è:
+\begin{functions}
+ \headdecl{unistd.h}
+ \headdecl{termios.h}
+
+ \funcdecl{int tcflow(int fd, int action)}
+
+ Sospende e rivvia il flusso dei dati sul terminale.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ errore, nel qual caso \var{errno} assumerà i valori \macro{EBADF} o
+ \macro{ENOTTY}.}
+\end{functions}
+
+La funzione permette di controllare (interrompendo e facendo riprendere) il
+flusso dei dati fra il terminale ed il sistema sia in ingresso che in uscita.
+Il comportamento della funzione è regolato dall'argomento \param{action}, i
+cui possibili valori, e relativa azione eseguita dalla funzione, sono
+riportati in \secref{tab:sess_tcflow_action}.
+
+\begin{table}[htb]
+ \footnotesize
+ \centering
+ \begin{tabular}[c]{|l|p{8cm}|}
+ \hline
+ \textbf{Valore}& \textbf{Azione}\\
+ \hline
+ \hline
+ \macro{TCOOFF}& Sospende l'output.\\
+ \macro{TCOON} & Riprende un output precedentemente sospeso.\\
+ \macro{TCIOFF}& Il sistema trasmette un carattere di STOP, che
+ fa interrompere la trasmissione dei dati dal terminale. \\
+ \macro{TCION} & Il sistema trasmette un carattere di START, che
+ fa riprendere la trasmissione dei dati dal terminale.\\
+ \hline
+ \end{tabular}
+ \caption{Possibili valori per l'argomento \param{action} della
+ funzione \func{tcflow}.}
+ \label{tab:sess_tcflow_action}
+\end{table}
-Il modo non canonico
+\subsection{Operare in \textsl{modo non canonico}}
+\label{sec:term_non_canonical}
+
+Operare con un terminale in modo canonico è relativamente semplice; basta
+eseguire una lettura e la funzione ritornerà quando una il driver del
+terminale avrà completato una linea di input. Non è detto che la linea sia
+letta interamente (si può aver richiesto un numero inferiore di byte) ma in
+ogni caso nessun dato verrà perso, e il resto della linea sarà letto alla
+chiamata successiva.
+
+Inoltre in modo canonico la gestione dell'input è di norma eseguita
+direttamente dal driver del terminale, che si incarica (a seconda di quanto
+impostato con le funzioni viste nei paragrafi precedenti) di cancellare i
+caratteri, bloccare e riavviare il flusso dei dati, terminare la linea quando
+viene ricevuti uno dei vari caratteri di terminazione (NL, EOL, EOL2, EOF).
+
+In modo non canonico tocca invece al programma gestire tutto quanto, i
+caratteri NL, EOL, EOL2, EOF, ERASE, KILL, CR, REPRINT non vengono
+interpretati automaticamente ed inoltre, non dividendo più l'input in linee,
+il sistema non ha più un limite definito per quando ritornare i dati ad un
+processo. Per questo motivo abbiamo visto che in \var{c\_cc} sono previsti due
+caratteri speciali, MIN e TIME (specificati dagli indici \macro{VMIN} e
+\macro{VTIME} in \var{c\_cc}) che dicono al sistema di ritornare da una
+\func{read} quando è stata letta una determinata quantità di dati o è passato
+un certo tempo.
+
+Come accennato nella relativa spiegazione in \tabref{tab:sess_termios_cc},
+TIME e MIN non sono in realtà caratteri ma valori numerici. Il comportamento
+del sistema per un terminale in modalità non canonica prevede quattro casi
+distinti:
+\begin{description}
+\item[MIN$>0$, TIME$>0$] In questo caso MIN stabilisce il numero minimo di
+ caratteri desiderati e TIME un tempo di attesa, in decimi di secondo, fra un
+ carattere e l'altro. Una \func{read} ritorna se vengono ricevuti almeno MIN
+ caratteri prima della scadenza di TIME (MIN è solo un limite inferiore, se
+ la funzione ha richiesto un numero maggiore di caratteri ne possono essere
+ restituiti di più); se invece TIME scade vengono restituiti i byte ricevuti
+ fino ad allora (un carattere viene sempre letto, dato che il timer inizia a
+ scorrere solo dopo la ricezione del primo carattere).
+\item[MIN$>0$, TIME$=0$] Una \func{read} ritorna solo dopo che sono stati
+ ricevuti almeno MIN caratteri. Questo significa che una \func{read} può
+ bloccarsi indefinitamente.
+\item[MIN$=0$, TIME$>0$] In questo caso TIME indica un tempo di attesa dalla
+ chiamata di \func{read}, la funzione ritorna non appena viene ricevuto un
+ carattere o scade il tempo. Si noti che è possibile che \func{read} ritorni
+ con un valore nullo.
+\item[MIN$=0$, TIME$=0$] In questo caso una \func{read} ritorna immediatamente
+ restituendo tutti i caratteri ricevuti. Anche in questo caso può ritornare
+ con un valore nullo.
+\end{description}