Altre funzioni per gli errori
[gapil.git] / system.tex
index 18cee493a4d73befeffd46495823ddb867ee9cd8..1e5a20f878d802c0e87002f56354df4d592b8d25 100644 (file)
@@ -903,14 +903,14 @@ struct statfs {
 
 
 Le \acr{glibc} provvedono infine una serie di funzioni per la gestione dei due
-file standard \file{/etc/fstab} e \file{/etc/mtab}, che convenzionalmente sono
-usati in quasi tutti i sistemi unix-like per mantenere rispettivamente le
-informazioni riguardo ai filesystem da montare e a quelli correntemente
-montati. Le funzioni servono a leggere il contenuto di questi file in
-opportune strutture \var{struct fstab} e \var{struct mntent}, e, per
-\file{/etc/mtab} per inserire e rimuovere le voci presenti nel file.  
-
-In generale si dovrebbero usare queste funzioni (in particolar modo quelle
+file \file{/etc/fstab} ed \file{/etc/mtab}, che convenzionalmente sono usati in
+quasi tutti i sistemi unix-like per mantenere rispettivamente le informazioni
+riguardo ai filesystem da montare e a quelli correntemente montati. Le
+funzioni servono a leggere il contenuto di questi file in opportune strutture
+\var{struct fstab} e \var{struct mntent}, e, per \file{/etc/mtab} per inserire
+e rimuovere le voci presenti nel file.
+
+In generale si dovrebbero usare queste funzioni (in particolare quelle
 relative a \file{/etc/mtab}), quando si debba scrivere un programma che
 effettua il montaggio di un filesystem; in realtà in questi casi è molto più
 semplice invocare direttamente il programma \cmd{mount}, per cui ne
@@ -1848,8 +1848,8 @@ norma l'uso delle funzioni precedenti 
 sostituite da \func{gettimeofday} e \func{settimeofday},\footnote{le due
   funzioni \func{time} e \func{stime} sono più antiche e derivano da SVr4,
   \func{gettimeofday} e \func{settimeofday} sono state introdotte da BSD, ed
-  in BSD4.3 sono indicate come sostitute delle precedenti.}  mentre i cui
-prototipi sono:
+  in BSD4.3 sono indicate come sostitute delle precedenti.} i cui prototipi
+sono:
 \begin{functions}
   \headdecl{sys/time.h}
   \headdecl{time.h}
@@ -1871,7 +1871,7 @@ prototipi sono:
 
 Queste funzioni utilizzano una struttura di tipo \var{timeval}, la cui
 definizione, insieme a quella della analoga \var{timespec}, è riportata in
-\figref{fig:sys_timeval_struct}. Le \acr{glibc} infatti provvedono queste due
+\figref{fig:sys_timeval_struct}. Le \acr{glibc} infatti forniscono queste due
 rappresentazioni alternative del \textit{calendar time} che rispetto a
 \type{time\_t} consentono rispettivamente precisioni del microsecondo e del
 nanosecondo.\footnote{la precisione è solo teorica, la precisione reale della
@@ -1911,11 +1911,12 @@ non 
 pertanto deve essere sempre settato a \macro{NULL}.
 
 Modificare l'orologio di sistema con queste funzioni è comunque problematico,
-in quanto esse effettuano un cambiamento immediato. Ad esempio se si porta
-avanti l'orologio si possono perdere delle esecuzioni di \cmd{cron}
-programmate nell'intervallo che si è saltato. Per questo motivo la modalità
-più corretta per settare l'ora è quella di usare la funzione \func{adjtime},
-il cui prototipo è:
+in quanto esse effettuano un cambiamento immediato. Questo può creare dei
+buchi o delle ripetizioni nello scorrere dell'orologio di sistema, con
+conseguenze indesiderate; ad esempio se si porta avanti l'orologio si possono
+perdere delle esecuzioni di \cmd{cron} programmate nell'intervallo che si è
+saltato. Per questo motivo la modalità più corretta per settare l'ora è quella
+di usare la funzione \func{adjtime}, il cui prototipo è:
 \begin{prototype}{sys/time.h}
 {int adjtime(const struct timeval *delta, struct timeval *olddelta)} 
   
@@ -1926,8 +1927,8 @@ il cui prototipo 
 \end{prototype}
 
 Questa funzione permette di avere un aggiustamento graduale del tempo di
-sistema in modo che esso sia sempre monotonicamente crescente. Il valore di
-\param{delta} esprime il valore di cui si vuole spostare l'orologio; se è
+sistema in modo che esso sia sempre crescente in maniera monotona. Il valore
+di \param{delta} esprime il valore di cui si vuole spostare l'orologio; se è
 positivo l'orologio sarà accelerato per un certo tempo in modo da guadagnare
 il tempo richiesto, altrimenti sarà rallentato. Il secondo parametro viene
 usato, se non nullo, per ricevere il valore dell'ultimo aggiustamento
@@ -2289,39 +2290,59 @@ riportare in opportuni messaggi le condizioni di errore verificatesi.  La
 prima funzione che si può usare per ricavare i messaggi di errore è
 \func{strerror}, il cui prototipo è:
 \begin{prototype}{string.h}{char *strerror(int errnum)} 
-  Ritorna una stringa (statica) che descrive l'errore il cui codice è passato
-  come parametro.
+  Restituisce una stringa con il messaggio di errore relativo ad
+  \param{errnum}.
+  
+  \bodydesc{La funzione ritorna il puntatore alla stringa col messaggio di
+    errore in caso di successo e \macro{NULL} in caso di errore, nel qual caso
+    \var{errno} sarà settata a \macro{EINVAL} se si è specificato un numero di
+    errore non valido.}
 \end{prototype}
 
 In generale \func{strerror} viene usata passando \var{errno} come parametro;
 nel caso si specifichi un codice sbagliato verrà restituito un messaggio di
-errore sconosciuto. La funzione utilizza una stringa statica che non deve
-essere modificata dal programma e che è utilizzabile solo fino ad una chiamata
-successiva a \func{strerror}; nel caso si usino i thread è
-provvista\footnote{questa funzione è una estensione GNU, non fa parte dello
-  standard POSIX.} una versione apposita:
+errore sconosciuto, e la funzione restituirà come errore \macro{EINVAL}. La
+funzione tiene conto del valore della variabile di ambiente
+\macro{LC\_MESSAGES} per usare eventuali traduzioni dei messaggi d'errore
+nella localizzazione presente. 
+
+La funzione utilizza una stringa statica che non deve essere modificata dal
+programma e che è utilizzabile solo fino ad una chiamata successiva a
+\func{strerror}; per questo motivo non è rientrante e nel caso si usino i
+thread è provvista\footnote{questa funzione è la versione prevista dalle
+  \acr{glibc}, ed effettivamente definita in \file{string.h}, ne esiste una
+  analoga nello standard SUSv3 (quella riportata dalla man page), che
+  restituisce \code{int} al posto di \code{char *}, e che tronca la stringa
+  restituita a \param{size}.} una versione apposita:
 \begin{prototype}{string.h}
-{char *strerror\_r(int errnum, char *buff, size\_t size)} 
-  Analoga a \func{strerror} ma ritorna il messaggio in un buffer
-  specificato da \param{buff} di lunghezza massima (compreso il terminatore)
-  \param{size}.
+  {char * strerror\_r(int errnum, char *buf, size\_t size)} 
+  
+  Analoga a \func{strerror} ma usa il buffer \param{buf} di lunghezza massima
+  (compreso il terminatore) \param{size}.
+  
+  \bodydesc{La funzione restitusce il puntatore alla stringa; in caso di
+    errore \var{errno} oltre a \macro{EINVAL} può assumere anche il valore
+    \macro{ERANGE} per indicare che non c'è sufficiente memoria per contenere
+    la stringa di descrizione.}
 \end{prototype}
 \noindent
 che utilizza un buffer che il singolo thread deve allocare, per evitare i
-problemi connessi alla condivisione del buffer statico. Infine, per completare
-la caratterizzazione dell'errore, si può usare anche la variabile
-globale\footnote{anche questa è un'estensione GNU.}
-\var{program\_invocation\_short\_name} che riporta il nome del programma
-attualmente in esecuzione.
+problemi connessi alla condivisione del buffer statico. La funzione
+restituisce l'indirizzo della stringa usata, che può essere contenuta nel
+buffer specificato da \param{buf}, per una lunghezza non superiore a
+\param{size}, nel qual caso la stringa sarebbe troncata e terminata con
+\macro{NUL}.
+
 
 Una seconda funzione usata per riportare i codici di errore in maniera
 automatizzata sullo standard error (vedi \secref{sec:file_std_descr}) è
 \func{perror}, il cui prototipo è:
-\begin{prototype}{stdio.h}{void perror (const char *message)} 
+\begin{prototype}{stdio.h}{void perror(const char *message)} 
   Stampa il messaggio di errore relativo al valore corrente di \var{errno}
   sullo standard error; preceduto dalla stringa \var{message}.
 \end{prototype}
-i messaggi di errore stampati sono gli stessi di \func{strerror}, (riportati
+
+I messaggi di errore stampati sono gli stessi di \func{strerror}, (riportati
 in \capref{cha:errors}), e, usando il valore corrente di \var{errno}, si
 riferiscono all'ultimo errore avvenuto. La stringa specificata con
 \var{message} viene stampato prime del messaggio d'errore, seguita dai due
@@ -2338,18 +2359,6 @@ la prima contiene i puntatori alle stringhe di errore indicizzati da
 l'utilizzo di questa stringa è sostanzialmente equivalente a quello di
 \func{strerror}.
 
-In \nfig\ è riportata la sezione attinente del codice del programma
-\cmd{errcode}, che può essere usato per stampare i messaggi di errore e le
-costanti usate per identificare i singoli errori; il sorgente completo del
-programma è allegato nel file \file{ErrCode.c} e contiene pure la gestione
-delle opzioni e tutte le definizioni necessarie ad associare il valore
-numerico alla costante simbolica. In particolare si è riportata la sezione che
-converte la stringa passata come parametro in un intero (\texttt{\small
-  1--2}), controllando con i valori di ritorno di \func{strtol} che la
-conversione sia avvenuta correttamente (\texttt{\small 4--10}), e poi stampa,
-a seconda dell'opzione scelta il messaggio di errore (\texttt{\small 11--14})
-o la macro (\texttt{\small 15--17}) associate a quel codice.
-
 \begin{figure}[!htb]
   \footnotesize
   \begin{lstlisting}{}
@@ -2375,6 +2384,93 @@ o la macro (\texttt{\small 15--17}) associate a quel codice.
   \label{fig:sys_err_mess}
 \end{figure}
 
+In \figref{fig:sys_err_mess} è riportata la sezione attinente del codice del
+programma \cmd{errcode}, che può essere usato per stampare i messaggi di
+errore e le costanti usate per identificare i singoli errori; il sorgente
+completo del programma è allegato nel file \file{ErrCode.c} e contiene pure la
+gestione delle opzioni e tutte le definizioni necessarie ad associare il
+valore numerico alla costante simbolica. In particolare si è riportata la
+sezione che converte la stringa passata come parametro in un intero
+(\texttt{\small 1--2}), controllando con i valori di ritorno di \func{strtol}
+che la conversione sia avvenuta correttamente (\texttt{\small 4--10}), e poi
+stampa, a seconda dell'opzione scelta il messaggio di errore (\texttt{\small
+  11--14}) o la macro (\texttt{\small 15--17}) associate a quel codice.
+
+
+
+\subsection{Alcune estensioni GNU}
+\label{sec:sys_err_GNU}
+
+Le precedenti funzioni sono quelle definite ed usate nei vari standard; le
+\acr{glibc} hanno però introdotto una serie di estensioni ``GNU'' che
+forniscono alcune funzionalità aggiuntive per una gestione degli errori
+semplificata e più efficiente. 
+
+La prima estenzione consiste in due variabili, \code{char *
+  program\_invocation\_name} e \code{char * program\_invocation\_short\_name}
+servono per ricavare il nome del programma; queste sono utili quando si deve
+aggiungere il nome del programma (cosa comune quando si ha un programma che
+non viene lanciato da linea di comando e salva gli errori in un file di log)
+al messaggio d'errore. La prima contiene il nome usato per lanciare il
+programma (ed è equivalente ad \code{argv[0]}); la seconda mantiene solo il
+nome del programma (senza eventuali directory in testa).
+
+Uno dei problemi che si hanno con l'uso di \func{perror} è che non c'è
+flessibilità su quello che si può aggiungere al messaggio di errore, che può
+essere solo una stringa. In molte occasioni invece serve poter scrivere dei
+messaggi con maggiore informazione; ad esempio negli standard di
+programmazione GNU si richiede che ogni messaggio di errore sia preceduto dal
+nome del programma, ed in generale si può voler stampare il contenuto di
+qualche variabile; per questo le \acr{glibc} definiscono la funzione
+\func{error}, il cui prototipo è:
+\begin{prototype}{stdio.h}
+{void error(int status, int errnum, const char *format, ...)} 
+
+Stampa un messaggio di errore formattato.
+
+\bodydesc{La funzione non restituisce nulla e non riporta errori.}
+\end{prototype}
+
+La funzione fa parte delle estensioni GNU per la gestione degli errori,
+l'argomento \param{format} prende la stessa sintassi di \func{printf}, ed i
+relativi parametri devono essere forniti allo stesso modo, mentre
+\param{errnum} indica l'errore che si vuole segnalare (non viene quindi usato
+il valore corrente di \var{errno}); la funzione stampa sullo standard error il
+nome del programma, come indicato dalla variabile globale \var{program\_name},
+seguito da due punti ed uno spazio, poi dalla stringa generata da
+\param{format} e dagli argomenti seguenti, seguita da due punti ed uno spazio
+infine il messaggio di errore relativo ad \param{errnum}, il tutto è terminato
+da un a capo.
+
+Il comportamento della funzione può essere ulteriormente controllato se si
+definisce una variabile \var{error\_print\_progname} come puntatore ad una
+funzione \ctyp{void} che restituisce \ctyp{void} che si incarichi di stampare
+il nome del programma. 
+
+L'argomento \param{status} può essere usato per terminare direttamente il
+programma in caso di errore, nel qual caso \func{error} dopo la stampa del
+messaggio di errore chiama \func{exit} con questo stato di uscita. Se invece
+il valore è nullo \func{error} ritorna normalmente ma viene incrementata
+un'altra variabile globale, \var{error\_message\_count}, che tiene conto di
+quanti errori ci sono stati.
+
+Un'altra funzione per la stampa degli errori, ancora più sofisticata, è
+\func{error\_at\_line}, che prende due argomenti aggiuntivi per indicare linea
+e file su cui è avvenuto l'errore; il suo prototipo è:
+\begin{prototype}{stdio.h}
+{void error\_at\_line(int status, int errnum, const char *fname, 
+  unsigned int lineno, const char *format, ...)} 
+
+Stampa un messaggio di errore formattato.
+
+\bodydesc{La funzione non restituisce nulla e non riporta errori.}
+\end{prototype}
+\noindent ed il suo comportamento è identico a quello di \func{error} se non
+per il fatto che, separati con il solito due punti-spazio, vengono inseriti un
+nome di file indicato da \param{fname} ed un numero di linea subito dopo la
+stampa del nome del programma.
+
+
 
 
 %%% Local Variables: