From c1cec4e931bf5bc2659d292e27f77a95ab72bf83 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Wed, 9 Oct 2002 16:59:39 +0000 Subject: [PATCH] Completata tcsetattr e tcgetaddr, inserito nuovo esempio. --- intro.tex | 1 + session.tex | 334 +++++++++++++++++++++++++++++++++++------- sources/SetTermAttr.c | 70 +++++++++ 3 files changed, 353 insertions(+), 52 deletions(-) create mode 100644 sources/SetTermAttr.c diff --git a/intro.tex b/intro.tex index fcf632d..1fce943 100644 --- a/intro.tex +++ b/intro.tex @@ -331,6 +331,7 @@ dove si possono recuperare varie (e di norma piuttosto intricate) informazioni \begin{table}[htb] + \footnotesize \centering \begin{tabular}[c]{|l|l|l|l|} \hline diff --git a/session.tex b/session.tex index 82d4ff7..6424af1 100644 --- a/session.tex +++ b/session.tex @@ -989,7 +989,6 @@ 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, è @@ -1144,6 +1143,12 @@ 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 @@ -1153,17 +1158,20 @@ costanti utilizzate per identificarli \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 @@ -1171,10 +1179,10 @@ costanti utilizzate per identificarli \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 @@ -1195,7 +1203,6 @@ costanti utilizzate per identificarli \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 @@ -1203,48 +1210,79 @@ 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} +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 @@ -1260,11 +1298,23 @@ 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. -\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 @@ -1273,19 +1323,63 @@ significato e delle costanti utilizzate per identificarli 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 @@ -1293,22 +1387,158 @@ significato e delle costanti utilizzate per identificarli \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 +#include +#include + +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}} diff --git a/sources/SetTermAttr.c b/sources/SetTermAttr.c new file mode 100644 index 0000000..c41fef1 --- /dev/null +++ b/sources/SetTermAttr.c @@ -0,0 +1,70 @@ +/* SetTermAttr.c + * + * Copyright (C) 2002 Simone Piccardi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/**************************************************************** + * + * Routine SetTermAttr + * Routine to set a local attribute for a terminal + * + * Author: Simone Piccardi + * Jun. 2001 + * + * $Id: SetTermAttr.c,v 1.1 2002/10/09 16:59:39 piccardi Exp $ + * + ****************************************************************/ +#include +#include +#include + +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; +} + -- 2.30.2