Completata revisione capitolo 2, aggiunte le variadic function e
[gapil.git] / filestd.tex
index dcbb3381f146bb7cd6d0141571274232de019601..2e9b05af38d47538260c57eb57836ead8850735e 100644 (file)
@@ -2,9 +2,9 @@
 \label{cha:files_std_interface}
 
 Esamineremo in questo capitolo l'interfaccia standard ANSI C per i file,
-quella che viene comunemente detta interfaccia degli \textit{stream}.
-Dopo una breve sezione introduttiva tratteremo le funzioni base per la
-gestione dell'input/output, mentre tratteremo le caratteristiche più avanzate
+quella che viene comunemente detta interfaccia degli \textit{stream}.  Dopo
+una breve sezione introduttiva tratteremo le funzioni base per la gestione
+dell'input/output, mentre tratteremo le caratteristiche più avanzate
 dell'interfaccia nell'ultima sezione.
 
 
@@ -89,14 +89,14 @@ questi tre stream sono identificabili attraverso dei nomi simbolici
 definiti nell'header \file{stdio.h} che sono:
 
 \begin{itemize}
-\item \var{FILE * stdin} Lo \textit{standard input} cioè lo stream da
+\item \var{FILE *stdin} Lo \textit{standard input} cioè lo stream da
   cui il processo riceve ordinariamente i dati in ingresso. Normalmente
   è associato dalla shell all'input del terminale e prende i caratteri
   dalla tastiera.
-\item \var{FILE * stdout} Lo \textit{standard input} cioè lo stream su
+\item \var{FILE *stdout} Lo \textit{standard input} cioè lo stream su
   cui il processo invia ordinariamente i dati in uscita. Normalmente è
   associato dalla shell all'output del terminale e scrive sullo schermo.
-\item \var{FILE * stderr} Lo \textit{standard input} cioè lo stream su
+\item \var{FILE *stderr} Lo \textit{standard input} cioè lo stream su
   cui il processo è supposto inviare i messaggi di errore. Normalmente
   anch'esso è associato dalla shell all'output del terminale e scrive
   sullo schermo.
@@ -215,23 +215,23 @@ tre\footnote{\func{fopen} e \func{freopen} fanno parte dello standard
 prototipi sono:
 \begin{functions}
   \headdecl{stdio.h}
-  \funcdecl{FILE * fopen(const char * path, const char *mode)}
+  \funcdecl{FILE *fopen(const char *path, const char *mode)}
   Apre il file specificato da \param{path}.
-  \funcdecl{FILE * fdopen(int fildes, const char * mode)}
+  \funcdecl{FILE *fdopen(int fildes, const char *mode)}
   Associa uno stream al file descriptor \param{fildes}.
-  \funcdecl{FILE * freopen(const char * path, const char * mode, FILE *
-  stream)}
+  \funcdecl{FILE *freopen(const char *path, const char *mode, FILE *stream)}
   Apre il file specificato da \param{path} associandolo allo stream
   specificato da \param{stream}, se questo è già aperto prima lo chiude.
-
-  Le funzioni ritornano un puntatore valido in caso di successo e \macro{NULL}
-  in caso di errore, in tal caso \var{errno} viene settata al valore ricevuto
-  dalla funzione sottostante di cui è fallita l'esecuzione.
   
-  Gli errori pertanto possono essere quelli di \func{malloc} per tutte e tre
-  le funzioni, quelli \func{open} per \func{fopen}, quelli di \func{fcntl} per
-  \func{fdopen} e quelli di \func{fopen}, \func{fclose} e \func{fflush} per
-  \func{freopen}. 
+  \bodydesc{Le funzioni ritornano un puntatore valido in caso di
+    successo e \macro{NULL} in caso di errore, in tal caso \var{errno}
+    viene settata al valore ricevuto dalla funzione sottostante di cui è
+    fallita l'esecuzione.
+  
+    Gli errori pertanto possono essere quelli di \func{malloc} per tutte
+    e tre le funzioni, quelli \func{open} per \func{fopen}, quelli di
+    \func{fcntl} per \func{fdopen} e quelli di \func{fopen},
+    \func{fclose} e \func{fflush} per \func{freopen}.}
 \end{functions}
 
 Normalmente la funzione che si usa per aprire uno stream è \func{fopen},
@@ -334,25 +334,26 @@ una operazione nominalmente nulla come \func{fseek(file, 0, SEEK\_CUR)} 
 sufficiente a garantire la sincronizzazione.
 
 Una volta aperto lo stream, si può cambiare la modalità di bufferizzazione
-(vedi \secref{sec:file_buffering_ctrl}) fintanto che non si è effettuato
+(si veda \secref{sec:file_buffering_ctrl}) fintanto che non si è effettuato
 alcuna operazione di I/O sul file.
 
 Uno stream viene chiuso con la funzione \func{fclose} il cui prototipo è:
-\begin{prototype}{stdio.h}{int fclose(FILE * stream)}
+\begin{prototype}{stdio.h}{int fclose(FILE *stream)}
   Chiude lo stream \param{stream}. 
   
-  Restituisce 0 in caso di successo e \macro{EOF} in caso di errore, nel qual
-  caso setta \var{errno} a \macro{EBADF} se il file descriptor indicato da
-  \param{stream} non è valido, o uno dei valori specificati dalla sottostante
-  funzione che è fallita (\func{close}, \func{write} o \func{fflush}).
+  \bodydesc{Restituisce 0 in caso di successo e \macro{EOF} in caso di errore,
+    nel qual caso setta \var{errno} a \macro{EBADF} se il file descriptor
+    indicato da \param{stream} non è valido, o uno dei valori specificati
+    dalla sottostante funzione che è fallita (\func{close}, \func{write} o
+    \func{fflush}).}
 \end{prototype}
 
-La funzione effettua uno scarico di tutti i dati presenti nei buffer di
-uscita e scarta tutti i dati in ingresso, se era stato allocato un
-buffer per lo stream questo verrà rilasciato. La funzione effettua lo
-scarico solo per i dati presenti nei buffer in user space usati dalle
-\acr{glibc}; se si vuole essere sicuri che il kernel forzi la scrittura
-su disco occorrerà effettuare una \func{sync}.
+La funzione effettua lo scarico di tutti i dati presenti nei buffer di uscita
+e scarta tutti i dati in ingresso; se era stato allocato un buffer per lo
+stream questo verrà rilasciato. La funzione effettua lo scarico solo per i
+dati presenti nei buffer in user space usati dalle \acr{glibc}; se si vuole
+essere sicuri che il kernel forzi la scrittura su disco occorrerà effettuare
+una \func{sync} (vedi \secref{sec:file_sync}).
 
 Linux supporta, come estensione implementata dalle \acr{glibc}, anche una
 altra funzione, \func{fcloseall}, che serve a chiudere tutti i file, il suo
@@ -360,14 +361,14 @@ prototipo 
 \begin{prototype}{stdio.h}{int fcloseall(void)}
   Chiude tutti gli stream. 
   
-  Restituisce 0 se non ci sono errori ed \macro{EOF} altrimenti.
+  \bodydesc{Restituisce 0 se non ci sono errori ed \macro{EOF} altrimenti.}
 \end{prototype}
-la funzione esegue lo scarico dei dati bufferizzati in uscita e scarta quelli
-in ingresso, chiudendo tutti i file. Questa funzione è provvista solo per i
-casi di emergenza, quando si è verificato un errore ed il programma deve
-essere abortito, ma si vuole compiere qualche altra operazione dopo aver
-chiuso i file e prima di uscire (si ricordi quanto visto in
-\secref{sec:proc_exit}).
+\noindent la funzione esegue lo scarico dei dati bufferizzati in uscita
+e scarta quelli in ingresso, chiudendo tutti i file. Questa funzione è
+provvista solo per i casi di emergenza, quando si è verificato un errore
+ed il programma deve essere abortito, ma si vuole compiere qualche altra
+operazione dopo aver chiuso i file e prima di uscire (si ricordi quanto
+visto in \secref{sec:proc_exit}).
 
 
 \subsection{Lettura e scrittura su uno stream}
@@ -421,9 +422,9 @@ questi due flag possono essere riletti dalle funzioni:
   Controlla il flag di end-of-file di \param{stream}.
   \funcdecl{int ferror(FILE *stream)}
   Controlla il flag di errore di \param{stream}.
-
-  Entrambe le funzioni ritornano un valore diverso da zero se i relativi
-  flag sono settati. 
+  
+  \bodydesc{Entrambe le funzioni ritornano un valore diverso da zero se
+    i relativi flag sono settati.}
 \end{functions}
 \noindent si tenga presente comunque che la lettura di questi flag segnala
 soltanto che c'è stato un errore, o che si è raggiunta la fine del file in una
@@ -432,7 +433,7 @@ ogni volta che si chiama una funzione di libreria.
 
 Entrambi i flag (di errore e di end-of-file) possono essere cancellati usando
 la funzione \func{clearerr}, il cui prototipo è:
-\begin{prototype}{stdio.h}{void clearerr( FILE *stream)}
+\begin{prototype}{stdio.h}{void clearerr(FILE *stream)}
   Cancella i flag di errore ed end-of-file di \param{stream}. 
 \end{prototype}
 \noindent in genere si usa questa funziona una volta che si sia identificata e
@@ -451,19 +452,18 @@ formattati. Le due funzioni che si usano per l'I/O binario sono:
 \begin{functions}
   \headdecl{stdio.h} 
   
-  \funcdecl{size\_t fread(void * ptr, size\_t size, size\_t nmemb, FILE
-    * stream)}
+  \funcdecl{size\_t fread(void *ptr, size\_t size, size\_t nmemb, FILE
+    *stream)}
   
-  \funcdecl{size\_t fwrite(const void * ptr, size\_t size, size\_t
-    nmemb, FILE * stream)}
+  \funcdecl{size\_t fwrite(const void *ptr, size\_t size, size\_t
+    nmemb, FILE *stream)}
   
-  Le funzioni rispettivamente leggono e scrivono \param{nmemb} elementi
-  di dimensione \param{size} dal buffer \param{ptr} al file
-  \param{stream}.
+  Rispettivamente leggono e scrivono \param{nmemb} elementi di dimensione
+  \param{size} dal buffer \param{ptr} al file \param{stream}.
   
-  Entrambe le funzioni ritornano il numero di elementi letti o scritti,
-  in caso di errore o fine del file viene restituito un numero di
-  elementi inferiore al richiesto.
+  \bodydesc{Entrambe le funzioni ritornano il numero di elementi letti o
+    scritti, in caso di errore o fine del file viene restituito un numero di
+    elementi inferiore al richiesto.}
 \end{functions}
 
 In genere si usano queste funzioni quando si devono trasferire su file
@@ -471,7 +471,7 @@ blocchi di dati binari in maniera compatta e veloce; un primo caso di uso
 tipico è quello in cui si salva un vettore (o un certo numero dei suoi
 elementi) con una chiamata del tipo:
 \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
-int WriteVect(FILE * stream, double * vec, size_t nelem) 
+int WriteVect(FILE *stream, double *vec, size_t nelem) 
 {
     int size, nread;
     size = sizeof(*vec);
@@ -551,14 +551,14 @@ gestione delle applicazioni multi-thread (si veda
 \begin{functions}
   \headdecl{stdio.h} 
   
-  \funcdecl{size\_t fread\_unlocked(void * ptr, size\_t size, size\_t
-    nmemb, FILE * stream)}
+  \funcdecl{size\_t fread\_unlocked(void *ptr, size\_t size, size\_t
+    nmemb, FILE *stream)}
   
-  \funcdecl{size\_t fwrite\_unlocked(const void * ptr, size\_t size,
-    size\_t nmemb, FILE * stream)}
+  \funcdecl{size\_t fwrite\_unlocked(const void *ptr, size\_t size,
+    size\_t nmemb, FILE *stream)}
   
-  Le funzioni sono identiche alle analoghe \func{fread} e \func{fwrite}
-  ma non acquisiscono il lock implicito sullo stream.
+  \bodydesc{Le funzioni sono identiche alle analoghe \func{fread} e
+    \func{fwrite} ma non acquisiscono il lock implicito sullo stream.}
 \end{functions}
 \noindent entrambe le funzioni sono estensioni GNU previste solo dalle
 \acr{glibc}.
@@ -568,10 +568,9 @@ gestione delle applicazioni multi-thread (si veda
 \label{sec:file_char_io}
 
 La seconda modalità di input/output è quella a caratteri, in cui si
-trasferisce un carattere alla volta.
-
-Le funzioni per la lettura a caratteri sono tre, \func{fgetc},
-\func{getc} e \func{getchar}, i rispettivi prototipi sono:
+trasferisce un carattere alla volta.  Le funzioni per la lettura a
+caratteri sono tre, \func{fgetc}, \func{getc} e \func{getchar}, i
+rispettivi prototipi sono:
 \begin{functions}
   \headdecl{stdio.h} 
 
@@ -581,11 +580,11 @@ Le funzioni per la lettura a caratteri sono tre, \func{fgetc},
   \funcdecl{int fgetc(FILE *stream)} Legge un byte da \param{stream} e lo
   restituisce come intero. È una sempre una funzione.
   
-  \funcdecl{int getchar(void)} è equivalente a \func{getc(stdin)}.
+  \funcdecl{int getchar(void)} Equivalente a \func{getc(stdin)}.
   
-  Tutte queste funzioni leggono un byte alla volta, che viene restituito
-  come intero; in caso di errore o fine del file il valore di ritorno è
-  \macro{EOF}.
+  \bodydesc{Tutte queste funzioni leggono un byte alla volta, che viene
+    restituito come intero; in caso di errore o fine del file il valore
+    di ritorno è \macro{EOF}.}
 \end{functions}
 
 A parte \func{getchar}, che si usa in genere per leggere un carattere da
@@ -608,12 +607,13 @@ ad \type{int} (si usa \type{unsigned char} in modo da evitare
 l'espansione del segno). In questo modo il valore di ritorno è sempre
 positivo, tranne in caso di errore o fine del file.
 
-Nelle estenzioni GNU che provvedono la localizzazione sono definite tre
+Nelle estensioni GNU che provvedono la localizzazione sono definite tre
 funzioni equivalenti alle precedenti che invece di un carattere di un
 byte restituiscono un carattere in formato esteso (cioè di tipo
 \type{wint\_t}, il loro prototipo è:
 \begin{functions}
   \headdecl{stdio.h} 
+  \headdecl{wchar.h} 
   
   \funcdecl{wint\_t getwc(FILE *stream)} Legge un carattere esteso da
   \param{stream}. In genere è implementata come una macro.
@@ -621,10 +621,10 @@ byte restituiscono un carattere in formato esteso (cio
   \funcdecl{wint\_t fgetwc(FILE *stream)} Legge un carattere esteso da
   \param{stream} È una sempre una funzione.
   
-  \funcdecl{wint\_t getwchar(void)} è equivalente a \func{getwc(stdin)}.
+  \funcdecl{wint\_t getwchar(void)} Equivalente a \func{getwc(stdin)}.
   
-  Tutte queste funzioni leggono un carattere alla volta, in caso di
-  errore o fine del file il valore di ritorno è \macro{WEOF}.
+  \bodydesc{Tutte queste funzioni leggono un carattere alla volta, in
+    caso di errore o fine del file il valore di ritorno è \macro{WEOF}.}
 \end{functions}
 
 Per scrivere un carattere si possono usare tre funzioni analoghe alle
@@ -639,11 +639,11 @@ precedenti usate per leggere: \func{putc}, \func{fputc} e
   \funcdecl{int fputc(FILE *stream)} Scrive il carattere \param{c} su
   \param{stream}. È una sempre una funzione.
   
-  \funcdecl{int putchar(void)} è equivalente a \func{putc(stdin)}.
+  \funcdecl{int putchar(void)} Equivalente a \func{putc(stdin)}.
   
-\item \noindent Le funzioni scrivono sempre un carattere alla volta,
-  il cui valore viene restituito in caso di successo; in caso di errore
-  o fine del file il valore di ritorno è \macro{EOF}.
+  \bodydesc{Le funzioni scrivono sempre un carattere alla volta, il cui
+    valore viene restituito in caso di successo; in caso di errore o
+    fine del file il valore di ritorno è \macro{EOF}.}
 \end{functions}
 
 Tutte queste funzioni scrivono sempre un byte alla volta, anche se
@@ -653,9 +653,10 @@ sempre un intero; in caso di errore o fine del file il valore di ritorno
 è \macro{EOF}.
 
 Come nel caso dell'I/O binario le \acr{glibc} provvedono per ciascuna
-delle funzioni precedenti una seconda funzione, il cui nome è ottenuto
-aggiungendo un \func{\_unlocked}, che esegue esattamente le stesse
-operazioni evitando però il lock implicito dello stream.
+delle funzioni precedenti, come estensione GNU, una seconda funzione, il
+cui nome è ottenuto aggiungendo un \func{\_unlocked}, che esegue
+esattamente le stesse operazioni evitando però il lock implicito dello
+stream.
 
 Per compatibilità con SVID sono provviste anche due funzioni per leggere
 e scrivere una \textit{word} (che è sempre definita come \type{int}); i
@@ -666,47 +667,510 @@ loro prototipi sono:
   \funcdecl{int getw(FILE *stream)} Legge una parola da \param{stream}.
   \funcdecl{int putw(int w, FILE *stream)} Scrive la parola \param{w} su
   \param{stream}.
-
-  Le funzioni restituiscono la parola \param{w}, o \macro{EOF} in caso
-  di errore o di fine del file.
+  
+  \bodydesc{Le funzioni restituiscono la parola \param{w}, o \macro{EOF}
+    in caso di errore o di fine del file.}
 \end{functions}
-l'uso di queste funzioni è deprecato in favore dell'uso di \func{fread}
-e \func{fwrite}, in quanto non è possibile distinguere il valore -1 da una
-condizione di errore che restituisce \macro{EOF}.
+\noindent l'uso di queste funzioni è deprecato in favore dell'uso di
+\func{fread} e \func{fwrite}, in quanto non è possibile distinguere il
+valore -1 da una condizione di errore che restituisce \macro{EOF}.
+
+Una degli usi più frequenti dell'input/output a caratteri è nei
+programmi di \textit{parsing} in cui si analizza il testo; in questo
+contesto diventa utile poter analizzare il carattere successivo da uno
+stream senza estrarlo effettivamente (la tecnica è detta \textit{peeking
+  ahead}) in modo che il programma possa regolarsi sulla base avendo
+dato una \textsl{sbirciatina} a quello che viene dopo. 
+
+Nel nostro caso questo tipo di comportamento può essere realizzato prima
+leggendo il carattere, e poi rimandandolo indietro, cosicché ridiventi
+disponibile per una lettura successiva; la funzione che inverte la
+lettura si chiama \func{ungetc} ed il suo prototipo è:
+\begin{prototype}{stdio.h}{int ungetc(int c, FILE *stream)}
+  Rimanda indietro il carattere \param{c}, con un cast a \type{unsigned
+    char}, sullo stream \param{stream}.
+
+  \bodydesc{La funzione ritorna \param{c} in caso di successo e
+  \macro{EOF} in caso di errore.}
+\end{prototype}
+\noindent benché lo standard ANSI C preveda che l'operazione possa
+essere ripetuta per un numero arbitrario di caratteri, alle
+implementazioni è richiesto di garantire solo un livello; questo è
+quello che fa la \acr{glibc}, che richiede che avvenga un'altra
+operazione fra due \func{ungetc} successive.
+
+Non è necessario che il carattere che si manda indietro sia l'ultimo che
+si è letto, e non è necessario neanche avere letto nessun carattere
+prima di usare \func{ungetc}, ma di norma la funzione è intesa per
+essere usata per rimandare indietro l'ultimo carattere letto.
+
+Nel caso \param{c} sia un \macro{EOF} la funzione non fa nulla, e
+restituisce sempre \macro{EOF}; così si può usare \func{ungetc} anche
+con il risultato di una lettura alla fine del file.
+
+Se si è alla fine del file si può comunque rimandare indietro un
+carattere, il flag di end-of-file verrà automaticamente cancellato
+perché c'è un nuovo carattere disponibile che potrà essere riletto
+successivamente.
+
+Infine si tenga presente che \func{ungetc} non altera il contenuto del
+file, ma opera esclusivamente sul buffer interno. Se si esegue una
+qualunque delle operazioni di riposizionamento (vedi
+\secref{sec:file_fseek}) i caratteri rimandati indietro vengono
+scartati.
 
 
 \subsection{Input/output di linea}
 \label{sec:file_line_io}
 
-La terza ed ultima modalità di input/output non formattato è quello di
+La terza ed ultima modalità di input/output non formattato è quella di
 linea, in cui legge o scrive una riga alla volta; questa è una modalità
-molto usata, ma che presenta le caratteristiche più controverse.
+molto usata per l'I/O da terminale, ma che presenta le caratteristiche
+più controverse.
 
-Le funzioni per leggere una linea sono sostazialmente due, \func{gets} e
-\func{fgets}, i rispettivi prototipi sono:
+Le funzioni previste dallo standard ANSI C per leggere una linea sono
+sostanzialmente due, \func{gets} e \func{fgets}, i cui rispettivi
+prototipi sono:
 \begin{functions}
   \headdecl{stdio.h} 
   
-  \funcdecl{char * gets(char * string)} Scrive su \param{string} una
+  \funcdecl{char *gets(char *string)} Scrive su \param{string} una
   linea letta da \var{stdin}.
   
-  \funcdecl{char * fgets(char * string, int size, FILE *stream)}
+  \funcdecl{char *fgets(char *string, int size, FILE *stream)}
   Scrive su \param{string} la linea letta da \param{stream} per un
   massimo di \param{size} byte.
+  
+  \bodydesc{Le funzioni restituiscono l'indirizzo \param{string} in caso
+    di successo o \macro{NULL} in caso di errore.}
+\end{functions}
 
-  Le funzioni restituiscono della stringa letta o \macro{NULL} in caso
-  di errore.
+Entrambe le funzioni effettuano la lettura (dal file specificato
+\func{fgets}, dallo standard input \func{gets}) di una linea di
+caratteri (terminata dal carattere \textit{newline}, \verb|\n|), ma
+\func{gets} sostituisce \verb|\n| con uno zero, mentre \func{fgets}
+aggiunge uno zero dopo il \textit{newline}, che resta dentro la
+stringa. Se la lettura incontra la fine del file (o c'è un errore) viene
+restituito un \macro{NULL}, ed il buffer \param{buf} non viene toccato.
+
+L'uso di \func{gets} è deprecato e deve essere assolutamente evitato; la
+funzione infatti non controlla il numero di byte letti, per cui nel caso
+la stringa letta superi le dimensioni del buffer, si avrà un
+\textit{buffer overflow}, con sovrascrittura della memoria del processo
+adiacente al buffer. 
+
+Questa è una delle vulnerabilità più sfruttate per guadagnare accessi
+non autorizzati al sistema (i cosiddetti \textit{exploit}), basta
+infatti inviare una stringa sufficientemente lunga ed opportunamente
+forgiata per sovrascrivere gli indirizzi di ritorno nello stack
+(supposto che la \func{gets} sia stata chiamata da una subroutine), in
+modo da far ripartire l'esecuzione nel codice inviato nella stringa
+stessa (in genere uno \textit{shell code} cioè una sezione di programma
+lancia una shell).
+
+La funzione \func{fgets} non ha i precedenti problemi di \func{gets} in
+quanto prende in input la dimensione del buffer \param{size}, che non
+verrà mai ecceduta in lettura. La funzione legge fino ad un massimo di
+\param{size} caratteri (newline compreso), ed aggiunge uno zero di
+terminazione; questo comporta che la stringa possa essere al massimo di
+\var{size-1} caratteri.  Se la linea eccede la dimensione del buffer
+verranno letti solo \var{size-1} caratteri, ma la stringa sarà sempre
+terminata correttamente con uno zero finale; sarà possibile leggere i
+restanti caratteri in una chiamata successiva.
+
+Per la scrittura di una linea lo standard ANSI C prevede altre due
+funzioni, \func{fputs} e \func{puts}, analoghe a quelle di lettura, i
+rispettivi prototipi sono:
+\begin{functions}
+  \headdecl{stdio.h} 
+  
+  \funcdecl{int puts(const char *string)} Scrive su \var{stdout} la
+  linea \param{string}.
+  
+  \funcdecl{int fputs(const char *string, FILE *stream)} Scrive su
+  \param{stream} la linea \param{string}.
+  
+  \bodydesc{Le funzioni restituiscono un valore non negativo in caso di
+    successo o \macro{EOF} in caso di errore.}
 \end{functions}
 
+Dato che in questo caso si scrivono i dati in uscita \func{puts} non ha
+i problemi di \func{gets} ed è in genere la forma più immediata per
+scrivere messaggi sullo standard output; la funzione prende una stringa
+terminata da uno zero ed aggiunge automaticamente un newline. La
+differenza con \func{fputs} (a parte la possibilità di specificare un
+file diverso da \var{stdout}) è che quest'ultima non aggiunge il
+newline, che deve essere previsto esplicitamente. 
+
+Come per le funzioni di input/output a caratteri esistono le estensioni
+per leggere e scrivere caratteri estesi, i loro prototipi sono:
+\begin{functions}
+  \headdecl{wchar.h} 
+  \funcdecl{wchar\_t *fgetws(wchar\_t *ws, int n, FILE *stream)}
+  Legge un massimo di \param{n} caratteri estesi dal file
+  \param{stream} al buffer \param{ws}.
+  
+  \funcdecl{int fputws(const wchar\_t *ws, FILE *stream)} Scrive la
+  linea \param{ws} di caratteri estesi sul file \param{stream}.
+  
+  \bodydesc{Le funzioni ritornano rispettivamente \param{ws} o un numero
+    non negativo in caso di successo e \macro{NULL} o \macro{EOF} in
+    caso di errore o fine del file.}
+\end{functions}
+\noindent il comportamento è identico a quello di \func{fgets} e
+\func{fputs} solo che tutto (numero di caratteri massimo, terminatore
+della stringa, newline) è espresso in termini di caratteri estesi
+anziché di caratteri ASCII.
+
+Come nel caso dell'I/O binario e a caratteri nelle \acr{glibc} sono
+previste una serie di altre funzioni, estensione di tutte quelle
+illustrate finora (eccetto \func{gets} e \func{puts}), il cui nome si
+ottiene aggiungendo un \func{\_unlocked}, e che eseguono esattamente le
+stesse operazioni delle loro equivalenti, evitando però il lock
+implicito dello stream (vedi \secref{sec:file_stream_thread}).
+
+Come abbiamo visto, le funzioni di lettura per l'input/output di linea
+previste dallo standard ANSI C presentano svariati inconvenienti. Benché
+\func{fgets} non abbia i gravissimi problemi di \func{gets}, può
+comunque dare risultati ambigui se l'input contiene degli zeri; questi
+infatti saranno scritti sul buffer di uscita e la stringa in output
+apparirà come più corta dei byte effettivamente letti. Questa è una
+condizione che è sempre possibile controllare (deve essere presente un
+newline prima della effettiva conclusione della stringa presente nel
+buffer), ma a costo di una complicazione ulteriore della logica del
+programma. Lo stesso dicasi quando si deve gestire il caso di stringa
+che eccede le dimensioni del buffer.
+
+Per questo motivo le \acr{glibc} prevedono, come estensione GNU, due
+nuove funzioni per la gestione dell'input/output di linea, il cui uso
+permette di risolvere questi problemi. L'uso di queste funzioni deve
+essere attivato definendo la macro \macro{\_GNU\_SOURCE} prima di
+includere \file{stdio.h}. La prima delle due, \func{getline}, serve per
+leggere una linea terminata da un newline esattamente allo stesso modo
+di \func{fgets}, il suo prototipo è:
+\begin{prototype}{stdio.h}
+  {ssize\_t getline(char **buffer, size\_t *n, FILE *stream)} Legge una
+  linea dal file \param{stream} sul buffer indicato da \param{buffer}
+  riallocandolo se necessario (l'indirizzo del buffer e la sua
+  dimensione vengono sempre riscritte).
+
+  \bodydesc{La funzione ritorna il numero di caratteri letti in caso di
+  successo e -1 in caso di errore o di raggiungimento della fine del
+  file.}
+\end{prototype}
+
+La funzione permette di eseguire una lettura senza doversi preoccupare
+della eventuale lunghezza eccessiva della stringa da leggere. Essa
+prende come primo parametro l'indirizzo del puntatore al buffer su cui
+si vuole leggere la linea. Quest'ultimo \emph{deve} essere stato
+allocato in precedenza con una \func{malloc} (non si può passare
+l'indirizzo di un puntatore ad una variabile locale); come secondo
+parametro la funzione vuole l'indirizzo della variabile contenente le
+dimensioni del buffer suddetto.
+
+Se il buffer di destinazione è sufficientemente ampio la stringa viene
+scritta subito, altrimenti il buffer viene allargato usando
+\func{realloc} e la nuova dimensione ed il nuovo puntatore vengono
+passata indietro (si noti infatti come per entrambi i parametri si siano
+usati dei \textit{value result argument}, passando dei puntatori anzichè
+i valori delle variabili, secondo la tecnica spiegata in
+\secref{sec:proc_var_passing}).
+
+Se si passa alla funzione l'indirizzo ad un puntatore settato a
+\macro{NULL} e \var{*n} è zero, la funzione provvede da sola
+all'allocazione della memoria necessaria a contenere la linea. In tutti
+i casi si ottiene dalla funzione un puntatore all'inizio del testo della
+linea. Un esempio di codice può essere il seguente:
+\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+    size_t n = 0; 
+    char *ptr = NULL;
+    int nread;
+    FILE * file;
+    ...    
+    nread = getline(&ptr, &n, file);
+\end{lstlisting}
+e per evitare memory leak occorre ricordarsi di liberare \var{ptr} con
+una \func{free}.
+
+Il valore di ritorno della funzione indica il numero di caratteri letti
+dallo stream (quindi compreso il newline, ma non lo zero di
+terminazione); questo permette anche di distinguere eventuali zeri letti
+dallo stream da quello inserito dalla funzione per terminare la linea.
+Se si è alla fine del file e non si è potuto leggere nulla o c'è stato
+un errore la funzione restituisce -1.
+
+La seconda estensione GNU è una generalizzazione di \func{getline} per
+poter usare come separatore un carattere qualsiasi, la funzione si
+chiama \func{getdelim} ed il suo prototipo è:
+\begin{prototype}{stdio.h}
+{ssize\_t getdelim(char **buffer, size\_t *n, int delim, FILE *stream)} 
+  Identica a \func{getline} solo che usa \param{delim} al posto del
+  carattere di newline come separatore di linea.
+\end{prototype}
+
+Il comportamento di \func{getdelim} è identico a quello di
+\func{getline} (che può essere implementata da questa passando
+\verb|'\n'| come valore di \param{delim}).
 
 
 \subsection{Input/output formattato}
 \label{sec:file_formatted_io}
 
+L'ultima modalità di input/output è quella formattata, che è una delle
+caratteristiche più utilizzate delle librerie standard del C; in genere
+questa è la modalità in cui si esegue normalmente l'output su terminale
+poichè permette di stampare in maniera facile e veloce dati, tabelle e
+messaggi.
+
+L'output formattato viene eseguito con una delle 13 funzioni della
+famiglia \func{printf}; le tre più usate sono le seguenti:
+\begin{functions}
+  \headdecl{stdio.h} 
+  \funcdecl{int printf(const char *format, ...)} Stampa su \var{stdout}
+  gli argomenti, secondo il formato specificato da \param{format}.
+  
+  \funcdecl{int fprintf(FILE *stream, const char *format, ...)}  Stampa
+  su \param{stream} gli argomenti, secondo il formato specificato da
+  \param{format}.
+  
+  \funcdecl{int sprintf(char *str, const char *format, ...)} Stampa
+  sulla stringa \param{str} gli argomenti, secondo il formato
+  specificato da \param{format}.
+
+  \bodydesc{Le funzioni ritornano il numero di caratteri stampati.}
+\end{functions}
+\noindent le prime due servono per stampare su file (lo standard output
+o quello specificato) la terza permette di stampare su una stringa, in genere
+l'uso di \func{sprintf} è sconsigliato in quanto è possibile, se non si ha la
+sicurezza assoluta sulle dimensioni del risultato della stampa, eccedere le
+dimensioni di \param{str} con conseguente sovrascrittura di altre varibili e
+possibili buffer overflow; per questo motivo si consiglia l'uso
+dell'alternativa:
+\begin{prototype}{stdio.h}
+{snprintf(char *str, size\_t size, const char *format, ...)} 
+  Identica a \func{sprintf}, ma non scrive su \param{str} più di
+  \param{size} caratteri.
+\end{prototype}
+
+La parte più complessa di queste funzioni è il formato della stringa
+\param{format} che indica le conversioni da fare, da cui poi deriva il numero
+dei parametri che dovranno essere passati a seguire. La stringa è costituita
+da caratteri normali (tutti eccetto \texttt{\%}), che vengono passati
+invariati all'output, e da direttive di conversione, in cui devono essere
+sempre presenti il carattere \texttt{\%}, che introduce la direttiva, ed uno
+degli specificatori di conversione (riportati in \ntab) che la conclude. 
+
+\begin{table}[htb]
+  \centering
+  \begin{tabular}[c]{|l|l|p{10cm}|}
+    \hline
+    \textbf{Valore} & \textbf{Tipo} & \textbf{Significato} \\
+    \hline
+    \hline
+   \cmd{\%d} &\type{int}         & Stampa un numero intero in formato decimale
+                                   con segno \\
+   \cmd{\%i} &\type{int}         & Identico a \cmd{\%i} in output, \\
+   \cmd{\%o} &\type{unsigned int}& Stampa un numero intero come ottale\\
+   \cmd{\%u} &\type{unsigned int}& Stampa un numero intero in formato
+                                   decimale senza segno \\
+   \cmd{\%x}, 
+   \cmd{\%X} &\type{unsigned int}& Stampano un intero in formato esadecimale,
+                                   rispettivamente con lettere minuscole e
+                                   maiuscole. \\
+   \cmd{\%f} &\type{unsigned int}& Stampa un numero in virgola mobile con la
+                                   notazione a virgola fissa \\
+   \cmd{\%e}, 
+   \cmd{\%E} &\type{double} & Stampano un numero in virgola mobile con la
+                              notazione esponenziale, rispettivamente con
+                              lettere minuscole e maiuscole. \\
+   \cmd{\%g}, 
+   \cmd{\%G} &\type{double} & Stampano un numero in virgola mobile con la
+                              notazione più appropriate delle due precedenti,
+                              rispettivamente con lettere minuscole e
+                              maiuscole. \\
+   \cmd{\%a}, 
+   \cmd{\%A} &\type{double} & Stampano un numero in virgola mobile in
+                              notazione esadecimale frazionaria\\
+   \cmd{\%c} &\type{int}    & Stampa un carattere singolo\\
+   \cmd{\%s} &\type{char *} & Stampa una stringa \\
+   \cmd{\%p} &\type{void *} & Stampa il valore di un puntatore\\
+   \cmd{\%n} &\type{\&int}  & Prende il numero di caratteri stampati finora\\
+   \cmd{\%\%}&              & Stampa un \% \\
+    \hline
+  \end{tabular}
+  \caption{Valori possibili per gli specificatori di conversione in una
+    stringa di formato di \func{printf}.} 
+  \label{tab:file_format_spec}
+\end{table}
+
+
+Il formato di una direttiva di conversione prevede una serie di possibili
+elementi opzionali oltre al \cmd{\%} e allo specificatore di conversione; in
+generale essa è sempre del tipo:
+\begin{center}
+\begin{verbatim}
+% [n. parametro $] [flag] [[larghezza] [. precisione]] [tipo] conversione
+\end{verbatim}
+\end{center}
+in cui i valori opzionali sono indicati fra parentesi, e prevedono la
+presenza, in questo ordine, di: uno specificatore per il parametro da usare
+(terminato da un \cmd{\$}, uno o più flag (riassunti in
+\tabref{tab:file_format_flag}) che controllano il formato di stampa della
+conversione (riassunti in \tabref{tab:file_format_type}), uno specificatore di
+larghezza, eventualmente seguito (per i numeri in virgola mobile) da un
+specificatore di precisione, uno specificatore del tipo di dato (che ne indica
+la lunghezza).
+
+\begin{table}[htb]
+  \centering
+  \begin{tabular}[c]{|l|p{10cm}|}
+    \hline
+    \textbf{Valore} & \textbf{Significato}\\
+    \hline
+    \hline
+    \cmd{\#} & Chiede la conversione in forma alternativa. \\
+    \cmd{0}  & La conversione è riempita con zeri alla sinistra del valore.\\
+    \cmd{-}  & La conversione viene allineata a sinistra sul bordo del campo.\\
+    \cmd{' '}& Mette uno spazio prima di un numero con segno di valore 
+               positivo\\
+    \cmd{+}  & Mette sempre il segno ($+$ o $-$) prima di un numero.\\
+    \hline
+  \end{tabular}
+  \caption{I valori dei flag per il formato di \func{printf}}
+  \label{tab:file_format_flag}
+\end{table}
+
+Dettagli ulteriori sulle varie opzioni possono essere trovati nella man page
+di \func{printf} e nella documentazione delle \acr{glibc}.
+
+\begin{table}[htb]
+  \centering
+  \begin{tabular}[c]{|l|p{10cm}|}
+    \hline
+    \textbf{Valore} & \textbf{Significato} \\
+    \hline
+    \hline
+    \cmd{hh} & una conversione intera corriponde a un \type{char} con o senza
+               segno, o il puntatore per il numero dei parametri \cmd{n} è di 
+               tipo \type{char}.\\
+    \cmd{h}  & una conversione intera corriponde a uno \type{short} con o 
+               senza segno, o il puntatore per il numero dei parametri \cmd{n}
+               è di tipo \type{short}.\\
+    \cmd{l}  & una conversione intera corriponde a un \type{long} con o 
+               senza segno, o il puntatore per il numero dei parametri \cmd{n}
+               è di tipo \type{long}, o il carattere o la stringa seguenti
+               sono in formato esteso.\\ 
+    \cmd{ll} & una conversione intera corriponde a un \type{long long} con o 
+               senza segno, o il puntatore per il numero dei parametri \cmd{n}
+               è di tipo \type{long long}.\\
+    \cmd{L}  & una conversione in virgola mobile corrisponde a un
+               \type{double}.\\
+    \cmd{q}  & sinonimo di \cmd{ll}.\\
+    \cmd{j}  & una conversione intera corrisponde a un \type{intmax\_t} o 
+               \type{uintmax\_t}.\\
+    \cmd{z}  & una conversione intera corrisponde a un \type{size\_t} o 
+               \type{ssize\_t}.\\
+    \cmd{t}  & una conversione intera corrisponde a un \type{ptrdiff\_t}.\\
+    \hline
+  \end{tabular}
+  \caption{Il modificatore di tipo di dato per il formato di \func{printf}}
+  \label{tab:file_format_type}
+\end{table}
+
+Una versione alternativa delle funzioni di output formattato, che permettono
+di usare il puntatore ad una lista di argomenti (vedi \secref{proc_variadic}),
+sono le seguenti:
+\begin{functions}
+  \headdecl{stdio.h} 
+  
+  \funcdecl{int vprintf(const char *format, va\_list ap)} Stampa su
+  \var{stdout} gli argomenti della lista \param{ap}, secondo il formato
+  specificato da \param{format}.
+  
+  \funcdecl{int vfprintf(FILE *stream, const char *format, va\_list ap)}
+  Stampa su \param{stream} gli argomenti della lista \param{ap}, secondo il
+  formato specificato da \param{format}.
+  
+  \funcdecl{int vsprintf(char *str, const char *format, va\_list ap)} Stampa
+  sulla stringa \param{str} gli argomenti della lista \param{ap}, secondo il
+  formato specificato da \param{format}.
+
+  \bodydesc{Le funzioni ritornano il numero di caratteri stampati.}
+\end{functions}
+\noindent con queste funzioni diventa possibile selezionare gli argomenti che
+si vogliono passare ad una routine di stampa, passando direttamente la lista
+tramite il parametro \param{ap}. Per poter far questo ovviamente la lista dei
+parametri dovrà essere opportunamente trattata (l'argomento è esaminato in
+\secref{sec:proc_variadic}), e dopo l'esecuzione della funzione l'argomento
+\param{ap} non sarà più utilizzabile (in generale dovrebbe essere eseguito un
+\macro{va\_end(ap)} ma in Linux questo non è necessario). 
+
+Come per \func{sprintf} anche per \func{vsprintf} esiste una analoga
+\func{vsnprintf} che pone un limite sul numero di caratteri che vengono
+scritti sulla stringa di destinazione:
+\begin{prototype}{stdio.h}
+{vsnprintf(char *str, size\_t size, const char *format, va\_list ap)} 
+  Identica a \func{vsprintf}, ma non scrive su \param{str} più di
+  \param{size} caratteri.
+\end{prototype}
+
+Per evitare questi problemi con la stampa su stringhe di lunghezza
+insuffciente le \acr{glibc} supportano una estensione specifica GNU che alloca
+dinamicamente tutto lo spazio necessario; l'estensione si attiva al solito
+definendo \macro{\_GNU\_SOURCE}, 
+
 
 \subsection{Posizionamento su uno stream}
 \label{sec:file_fseek}
 
+Come per i file descriptor è possibile anche con gli stream spostarsi
+all'interno di un file per effettuare operazioni di lettura o scrittura in un
+punto prestabilito; questo fintanto che l'operazione di riposizionamento è
+supportata dal file sottostante lo stream, quando cioè si ha a che fare con
+quello che viene detto un file ad \textsl{accesso casuale}.
+
+In GNU/Linux ed in generale in ogni sistema unix-like la posizione nel
+file è espressa da un intero positivo, rappresentato dal tipo
+\type{off\_t}, il problema è alcune delle funzioni usate per il
+riposizionamento sugli stream originano dalle prime versioni di unix in
+cui questo tipo non era ancora stato definito, e che in altri sistemi
+non è detto che la posizione su un file venga sempre rappresentata con
+un numero di caratteri (ad esempio in VMS può essere rappresentata come
+numero di record, e offset rispetto al record corrente).
+
+Tutto questo comporta la presenza di diverse funzioni che eseguono
+sostanzialmente le stesse operazioni, ma usano parametri di tipo
+diverso. Le funzioni tradizionali usate per il riposizionamento della
+posizione in uno stream sono:
+\begin{functions}
+  \headdecl{stdio.h} 
+  
+  \funcdecl{int fseek(FILE *stream, long offset, int whence)} Sposta la
+  posizione nello stream secondo quanto specificato tramite \param{offset}
+  e \param{whence}.  
+
+  \funcdecl{void rewind(FILE *stream)} Riporta la posizione nello stream
+  all'inizio del file.
+\end{functions}
+
+L'uso di \func{fseek} è del tutto analogo a quello di \func{lseek} per i
+file descriptor, ed i parametri, a parte il tipo, hanno lo stesso
+significato; in particolare \param{whence} assume gli stessi valori già
+visti in \secref{sec:file_lseek}. La funzione restituisce 0 in caso di
+successo e -1 in caso di errore. 
+
+Per leggere la posizione corrente si usa invece la funzione \func{ftell}, il
+cui prototipo è:
+\begin{prototype}{stdio.h}{long ftell(FILE *stream)} 
+  Legge la posizione attuale nello stream.
+  
+  \bodydesc{La funzione restituisce la posizione corrente, o -1 in caso
+    di fallimento, che può esser dovuto sia al fatto che il file non
+    supporta il riposizionamento che al fatto che la posizione non può
+    essere espressa con un \type{long int}}
+\end{prototype}
+
+  
 
 
 \section{Funzioni avanzate}
@@ -734,10 +1198,10 @@ stream; questo pu
 \func{\_\_fwritable} i cui prototipi sono:
 \begin{functions}
   \headdecl{stdio\_ext.h}
-  \funcdecl{int \_\_freadable (FILE * stream)}
+  \funcdecl{int \_\_freadable (FILE *stream)}
   Restituisce un valore diverso da zero se \param{stream} consente la lettura.
 
-  \funcdecl{int \_\_fwritable(FILE * stream)}  
+  \funcdecl{int \_\_fwritable(FILE *stream)}  
   Restituisce un valore diverso da zero se \param{stream} consente la
   scrittura.
 \end{functions}
@@ -746,11 +1210,11 @@ Altre due funzioni, \func{\_\_freading} e \func{\_\_fwriting} servono ad un
 uso ancora più specialistico, il loro prototipo è: 
 \begin{functions}
   \headdecl{stdio\_ext.h}
-  \funcdecl{int \_\_freading (FILE * stream)}
+  \funcdecl{int \_\_freading (FILE *stream)}
   Restituisce un valore diverso da zero se \param{stream} è aperto in sola
   lettura o se l'ultima operazione è stata di lettura.
 
-  \funcdecl{int \_\_fwriting(FILE * stream)}  
+  \funcdecl{int \_\_fwriting(FILE *stream)}  
   Restituisce un valore diverso da zero se \param{stream} è aperto in sola
   scrittura o se l'ultima operazione è stata di scrittura.
 \end{functions}
@@ -780,7 +1244,7 @@ stream; se non si 
 
 Gli stream possono essere usati in applicazioni multi-thread allo stesso
 modo in cui sono usati nelle applicazioni normali, ma si deve essere
-consapovoli delle possibili complicazioni anche quando non si usano i
+consapevoli delle possibili complicazioni anche quando non si usano i
 thread, dato che l'implementazione delle librerie è influenzata
 pesantemente dalle richieste necessarie per garantirne l'uso coi thread.
 
@@ -789,16 +1253,16 @@ pesantemente dalle richieste necessarie per garantirne l'uso coi thread.
 \begin{functions}
   \headdecl{stdio.h}
   
-  \funcdecl{void flockfile(FILE * stream)} Esegue l'acquisizione del
+  \funcdecl{void flockfile(FILE *stream)} Esegue l'acquisizione del
   lock dello stream \param{stream}, bloccandosi in caso il lock non
   disponibile. 
   
-  \funcdecl{int ftrylockfile(FILE * stream)} Tenta l'acquisizione del
+  \funcdecl{int ftrylockfile(FILE *stream)} Tenta l'acquisizione del
   lock dello stream \param{stream}, senza bloccarsi in caso il lock non sia
   disponibile. Ritorna zero in caso di acquisizione del lock, diverso da
   zero altrimenti.
   
-  \funcdecl{void funlockfile(FILE * stream)} Rilascia il lock dello
+  \funcdecl{void funlockfile(FILE *stream)} Rilascia il lock dello
   stream \param{stream}.
 \end{functions}