\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, è
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
\hline
\hline
\macro{OPOST} & Se impostato i caratteri vengono convertiti opportunamente
- per la visulizzazione sul terminale, ad esempio al
+ (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 ritorno carrello, a capo (CR-LF).\\
- \macro{OLCUC} & Se impostato trasforma i caratteri minuscoli in caratteri
- maiuscoli sull'uscita.\\
- \macro{ONLCR} & Se impostato converte il carattere di a capo (NL) in
- ritorno carrello (CR).\\
- \macro{ONOCR} & Se impostato converte il ritorno carrello (CR) nella
- coppia CR-LF.\\
+ 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
\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, i valori possibili sono \macro{NL0} o
- \macro{NL1}.\\
+ 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, i valori possibili sono
+ 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
\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
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}
+che prima cancella i bit della maschera in questione e poi setta il valore.
+
+
\begin{table}[htb]
\footnotesize
\centering
- \begin{tabular}[c]{|l|p{10cm}|}
+ \begin{tabular}[c]{|l|p{13cm}|}
\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 venire
- ignorate. Se questo flag non è impostato una chiamata ad
- \func{open} per la quale non si sia impostato
- \macro{O\_NOBLOCK} si bloccherà finché non si sia
- stabilita una connessione con il modem, e se viene
- rilevata una disconessione viene inviato un
+ 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 vengono staccate le linee di
- connessione del modem quando non resta più nessun
- processo che ha un file aperto sul terminale.\\
- \macro{CREAD} & Se non è impostato l'input del terminale viene scartato.\\
+ \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 invece di uno.\\
+ seriale, se non impostato ne viene usato soltanto uno.\\
\macro{PARENB} & Se impostato abilita la generazione il controllo di
- parità. Se non è impostato i bit di parità non vengono
+ 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 è impostato \macro{PARENB}. Se impostato
- la parità è dispari, altrimenti è pari.\\
- \macro{CSIZE} & Maschera per i bit che indicano la dimensione del
- carattere, i valori possibili sono
- \macro{CS5}, \macro{CS6}, \macro{CS7} e \macro{CS8}.\\
+ \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}
+ corripondenti 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 Linux viene
+ 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.\\
+ 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 (RTS/CTS).\\
+ \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
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.
-\begin{table}[htb]
+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} (non mostrati in
+\secref{fig:term_termios}).
+
+\begin{table}[b!ht]
\footnotesize
\centering
- \begin{tabular}[c]{|l|p{10cm}|}
+ \begin{tabular}[c]{|l|p{13cm}|}
\hline
\textbf{Valore}& \textbf{Significato}\\
\hline
altrimenti opera in modo non canonico.\\
\macro{ECHO} & Se è impostato viene attivato l'eco dei caratteri in
input sull'output del terminale.\\
- \macro{ECHOE} & .\\
- \macro{ISIG} & .\\
- \macro{XCASE} & .\\
- \macro{ECHOK} & .\\
- \macro{ECHONL} & .\\
- \macro{ECHOPRT}& .\\
- \macro{ECHOKE} & .\\
- \macro{DEFECHO}& .\\
- \macro{FLUSHO} & .\\
- \macro{NOFLSH} & .\\
- \macro{TOSTOP} & .\\
- \macro{PENDIN} & .\\
- \macro{IEXTEN} & .\\
+ \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
\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}.
+riportato in \tabref{tab:sess_termios_lflag}.
+
+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}.
+
+Con i terminali odierni l'unico flag con cui probabilmente si può avere a che
+fare è questo, che è l'unico che concerne le caratteristiche generiche comuni
+a tutti i terminali.
+
+Per impostare tutti questi flag lo standard POSIX prevede due funzioni:
+\func{tcgetattr} e \func{tcsetattr}; entrambe prendono come parametro un
+puntatore ad struttura \var{termios} che deve essere oportunamente
+inizializzata, 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 identificato dal file descriptor \param{fd}
+utilizzando la struttura specificata dal puntatore \param{termios\_p} per lo
+scambio dei dati. Come già accennato i valori di ciascun bit devono essere
+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} si è riportato il codice delle due funzioni
+\func{SetTermAttr} e \func{UnSetTermAttr} che possono essere usate
+rispettivamente per impostare o rimuovere un qualunque bit di \var{c\_lflag},
+con le dovute precauzioni. Il codice di entrambe le funzioni può essere
+trovato nel file \file{SetTermAttr.c} dei sorgenti allegati.
+
+\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;
+}
+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 delle funzioni \func{SetTermAttr} e \func{UnSetTermAttr} per
+ impostare o rimuovere uno dei flag di controllo locale del terminale.}
+ \label{fig:term_set_attr}
+\end{figure}
+La prima funzione 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.
+
+La seconda funzione è identica alla prima, solo che in questo caso
+(\texttt{\small 33}) si rimuovono i bit specificati dall'argomento
+\param{flag} usando un AND binario del valore negato.
+
+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
+\ref{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{13cm}|}
+ \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}
+Infine occorre tenere presente che \func{tcsetattr} ritorna con successo anche
+se uno qualunque 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
\subsection{Il \textsl{modo canonico}}
\label{sec:term_canonic_mode}
-Il modo canonico
+Il modo canonico
\subsection{Il \textsl{modo non canonico}}