+Si tenga presente che i flag che riguardano le modalità di eco dei caratteri
+(\const{ECHOE}, \const{ECHOPRT}, \const{ECHOK}, \const{ECHOKE},
+\const{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 \const{ICANON}.
+
+Oltre ai vari flag per gestire le varie caratteristiche dei terminali,
+\struct{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 \const{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{9cm}|}
+ \hline
+ \textbf{Indice} & \textbf{Valore}&\textbf{Codice} & \textbf{Funzione}\\
+ \hline
+ \hline
+ \const{VINTR} &\texttt{0x03}&(\texttt{C-c})& Carattere di interrupt,
+ provoca l'emissione di
+ \const{SIGINT}.\\
+ \const{VQUIT} &\texttt{0x1C}&(\texttt{C-\bslash})& Carattere di uscita,
+ provoca l'emissione di
+ \const{SIGQUIT}.\\
+ \const{VERASE}&\texttt{0x7f}&DEL,\texttt{C-?}& Carattere di ERASE, cancella
+ l'ultimo carattere
+ precedente nella linea.\\
+ \const{VKILL} &\texttt{0x15}&(\texttt{C-u})& Carattere di KILL, cancella
+ l'intera riga.\\
+ \const{VEOF} &\texttt{0x04}&(\texttt{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}.\\
+ \const{VMIN} & --- & --- & Numero minimo di caratteri per una
+ lettura in modo non canonico.\\
+ \const{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.\\
+ \const{VTIME} & --- & --- & Timeout, in decimi di secondo, per
+ una lettura in modo non canonico.\\
+ \const{VEOL2} &\texttt{0x00}& NUL & Ulteriore carattere di fine
+ riga. Ha lo stesso effetto di
+ \const{VEOL} ma può essere un
+ carattere diverso. \\
+ \const{VSWTC} &\texttt{0x00}& NUL & Carattere di switch. Non supportato
+ in Linux.\\
+ \const{VSTART}&\texttt{0x17}&(\texttt{C-q})& Carattere di START. Riavvia un
+ output bloccato da uno STOP.\\
+ \const{VSTOP} &\texttt{0x19}&(\texttt{C-s})& Carattere di STOP. Blocca
+ l'output fintanto che non
+ viene premuto un carattere di
+ START.\\
+ \const{VSUSP} &\texttt{0x1A}&(\texttt{C-z})& Carattere di
+ sospensione. Invia il segnale
+ \const{SIGTSTP}.\\
+ \const{VDSUSP}&\texttt{0x19}&(\texttt{C-y})& Carattere di sospensione
+ ritardata. Invia il segnale
+ \const{SIGTSTP} quando il
+ carattere viene letto dal
+ programma, (non presente in
+ POSIX e non riconosciuto in
+ Linux).\\
+ \const{VLNEXT}&\texttt{0x16}&(\texttt{C-v})& Carattere di escape, serve a
+ quotare il carattere
+ successivo che non viene
+ interpretato ma passato
+ direttamente all'output.\\
+ \const{VWERASE}&\texttt{0x17}&(\texttt{C-w})&Cancellazione di una
+ parola.\\
+ \const{VREPRINT}&\texttt{0x12}&(\texttt{C-r})& Ristampa i caratteri non
+ ancora letti (non presente in
+ POSIX).\\
+ \const{VDISCARD}&\texttt{0x0F}&(\texttt{C-o})& Non riconosciuto in Linux.\\
+ \const{VSTATUS} &\texttt{0x13}&(\texttt{C-t})& Non riconosciuto in Linux.\\
+ \hline
+ \end{tabular}
+ \caption{Valori dei caratteri di controllo mantenuti nel campo \var{c\_cc}
+ della struttura \struct{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 tab.~\ref{tab:sess_termios_cc}, usando quelle
+definizioni diventa possibile assegnare un nuovo carattere di controllo con un
+codice del tipo:
+\includecodesnip{listati/value_c_cc.c}
+
+La maggior parte di questi caratteri (tutti tranne \const{VTIME} e
+\const{VMIN}) hanno effetto solo quando il terminale viene utilizzato in modo
+canonico; per alcuni devono essere soddisfatte ulteriori richieste, ad esempio
+\const{VINTR}, \const{VSUSP}, e \const{VQUIT} richiedono sia impostato
+\const{ISIG}; \const{VSTART} e \const{VSTOP} richiedono sia impostato
+\const{IXON}; \const{VLNEXT}, \const{VWERASE}, \const{VREPRINT} richiedono sia
+impostato \const{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 varie impostazioni dei terminali viste finora
+lo standard POSIX prevede due funzioni che utilizzano come argomento un
+puntatore ad una struttura \struct{termios} che sarà quella in cui andranno
+immagazzinate le impostazioni. Le funzioni sono \funcd{tcgetattr} e
+\funcd{tcsetattr} ed 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[\errcode{EINTR}] la funzione è stata interrotta.
+ \end{errlist}
+ ed inoltre \errval{EBADF}, \errval{ENOTTY} ed \errval{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 \const{SIGTTOU} come
+se si fosse tentata una scrittura, a meno che il processo chiamante non abbia
+\const{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
+tab.~\ref{tab:sess_tcsetattr_option}; di norma (come fatto per le due funzioni
+di esempio) si usa sempre \const{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
+ \const{TCSANOW} & Esegue i cambiamenti in maniera immediata.\\
+ \const{TCSADRAIN}& I cambiamenti vengono eseguiti dopo aver atteso che
+ tutto l'output presente sulle code è stato scritto.\\
+ \const{TCSAFLUSH}& È identico a \const{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 \centering
+ \begin{minipage}[c]{15cm}
+ \includecodesample{listati/SetTermAttr.c}
+ \end{minipage}
+ \normalsize
+ \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 fig.~\ref{fig:term_set_attr} e fig.~\ref{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 completo
+di entrambe le funzioni può essere trovato nel file \file{SetTermAttr.c} dei
+sorgenti allegati alla guida.
+
+La funzione \func{SetTermAttr} provvede ad impostare il bit specificato
+dall'argomento \param{flag}; prima si leggono i valori correnti
+(\texttt{\small 8}) con \func{tcgetattr}, uscendo con un messaggio in caso di
+errore (\texttt{\small 9--10}), poi si provvede a impostare solo i bit
+richiesti (possono essere più di uno) con un OR binario (\texttt{\small 12});
+infine si scrive il nuovo valore modificato con \func{tcsetattr}
+(\texttt{\small 13}), notificando un eventuale errore (\texttt{\small 14-15})
+o uscendo normalmente.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includecodesample{listati/UnSetTermAttr.c}
+ \end{minipage}
+ \normalsize
+ \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 (\texttt{\small 9}) 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
+\struct{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,
+\funcd{cfsetispeed} per la velocità della linea di ingresso e
+\funcd{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 \param{speed} all'interno della struttura puntata da
+\param{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 (\val{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.
+
+Dato che in genere si imposta sempre la stessa velocità sulle linee di uscita
+e di ingresso è supportata anche la funzione \funcd{cfsetspeed}, una
+estensione di BSD,\footnote{la funzione origina da 4.4BSD e richiede sua
+ definita la macro \macro{\_BSD\_SOURCE}.} il cui prototipo è:
+\begin{functions}
+ \headdecl{unistd.h}
+ \headdecl{termios.h}
+ \funcdecl{int cfsetspeed(struct termios *termios\_p, speed\_t speed)}
+ Imposta la velocità delle linee seriali.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ errore, che avviene solo quando il valore specificato non è valido.}
+\end{functions}
+\noindent la funzione è identica alle due precedenti ma imposta la stessa
+velocità sia per la linea di ingresso che per quella di uscita.
+
+Analogamente a quanto avviene per l'impostazione, le velocità possono essere
+lette da una struttura \struct{termios} utilizzando altre due funzioni,
+\funcd{cfgetispeed} e \funcd{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{tcgetattr}.
+
+Infine sempre da BSD è stata ripresa una funzione che consente di impostare il
+teminale in una modalità analoga all cosiddetta modalità ``\textit{raw}'' di
+System V, in cui i dati in input vengono resi disponibili un carattere alla
+volta, e l'echo e tutte le interpretazioni dei caratteri in entrata e uscita
+sono disabilitate. La funzione è \funcd{cfmakeraw} ed il suo prototipo è:
+\begin{functions}
+ \headdecl{unistd.h}
+ \headdecl{termios.h}
+ \funcdecl{void cfmakeraw(struct termios *termios\_p)}
+ Importa il terminale in modalità ``\textit{raw}'' alla System V.
+
+ \bodydesc{La funzione imposta solo i valori in \param{termios\_p}, e non
+ sono previste condizioni di errore.}
+\end{functions}
+
+Anche in questo caso la funzione si limita a preparare i valori che poi
+saranno impostato con una successiva chiamata a \func{tcsetattr}, in sostanza
+la funzione è equivalente a:
+\includecodesnip{listati/cfmakeraw.c}
+
+
+\subsection{La gestione della disciplina di linea.}
+\label{sec:term_line_discipline}
+
+Come illustrato dalla struttura riportata in fig.~\ref{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}.
+
+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 \const{SIGTTOU} come
+illustrato in sez.~\ref{sec:sess_ctrl_term}.\footnote{con la stessa eccezione,
+ già vista per \func{tcsetattr}, che quest'ultimo sia bloccato o ignorato dal
+ processo chiamante.}
+
+Una prima funzione, che è efficace solo in caso di terminali seriali asincroni
+(non fa niente per tutti gli altri terminali), è \funcd{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 \errval{EBADF} o
+ \errval{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{lo standard 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 è
+\funcd{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 \errval{EBADF} o
+ \errval{ENOTTY}.}
+\end{functions}