Correzioni rimaste indietro ed espansione funzioni del resolver.
authorSimone Piccardi <piccardi@gnulinux.it>
Mon, 7 Nov 2016 20:02:45 +0000 (20:02 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Mon, 7 Nov 2016 20:02:45 +0000 (20:02 +0000)
listati/poll_echod.c
listati/resolv_newoption.c [new file with mode: 0644]
listati/resolv_option.c
listati/select_echod.c
prochand.tex
session.tex
sockctrl.tex
system.tex
tcpsock.tex

index e2e2a9612211c061ddb7aee75f2316b2901e8e55..87eeb9f084ed65040a9c77fd186f41206aa4d74b 100644 (file)
@@ -1,15 +1,13 @@
-    /* initialize all needed variables */
+...
     poll_set = (struct pollfd *) malloc(n * sizeof(struct pollfd));
     max_fd = list_fd;                 /* maximum now is listening socket */
     poll_set = (struct pollfd *) malloc(n * sizeof(struct pollfd));
     max_fd = list_fd;                 /* maximum now is listening socket */
-    for (i=0; i<n; i++) {
+    for (i=0; i<n; i++) {             /* initialize poll set */
        poll_set[i].fd = -1;
        poll_set[i].events = POLLRDNORM;
     }
        poll_set[i].fd = -1;
        poll_set[i].events = POLLRDNORM;
     }
-    poll_set[max_fd].fd = list_fd;
-    /* main loop, wait for connection and data inside a select */
-    while (1) {    
-       while ( ((n = poll(poll_set, max_fd + 1, -1)) < 0) 
-               && (errno == EINTR));         /* wait for data or connection */
+    poll_set[max_fd].fd = list_fd;    
+    while (1) {   /* main loop, wait for connection and data inside a poll */
+       while ( ((n=poll(poll_set, max_fd + 1, -1)) < 0) && (errno == EINTR));
        if (n < 0) {                          /* on real error exit */
            PrintErr("poll error");
            exit(1);
        if (n < 0) {                          /* on real error exit */
            PrintErr("poll error");
            exit(1);
@@ -53,4 +51,4 @@
            }
        }
     }
            }
        }
     }
-    exit(0);     /* normal exit, never reached */
+...
diff --git a/listati/resolv_newoption.c b/listati/resolv_newoption.c
new file mode 100644 (file)
index 0000000..244808f
--- /dev/null
@@ -0,0 +1,2 @@
+struct __res_state;
+typedef struct __res_state *res_state;
index ebe8f92572154ecd3c3bafb968ae1b2b9f28d2de..b90f8b9d8202e3ca6d3c63423fc94c73a4976e0c 100644 (file)
@@ -1 +1 @@
-       extern struct state _res;
+extern struct __res_state _res;
index d06b14ea503d7a5b0ada8077284c8af060826780..7687310de7cdd4e19fe27fb04119483fb085a900 100644 (file)
@@ -2,12 +2,10 @@
     memset(fd_open, 0, FD_SETSIZE);   /* clear array of open files */
     max_fd = list_fd;                 /* maximum now is listening socket */
     fd_open[max_fd] = 1;
     memset(fd_open, 0, FD_SETSIZE);   /* clear array of open files */
     max_fd = list_fd;                 /* maximum now is listening socket */
     fd_open[max_fd] = 1;
-    /* main loop, wait for connection and data inside a select */
-    while (1) {  
-       FD_ZERO(&fset);               /* clear fd_set */
-       for (i = list_fd; i <= max_fd; i++) { /* initialize fd_set */
+    while (1) {   /* main loop, wait for connection and data inside a select */
+       FD_ZERO(&fset);                       /* clear fd_set */
+       for (i = list_fd; i <= max_fd; i++)   /* initialize fd_set */
            if (fd_open[i] != 0) FD_SET(i, &fset); 
            if (fd_open[i] != 0) FD_SET(i, &fset); 
-       }
        while ( ((n = select(max_fd + 1, &fset, NULL, NULL, NULL)) < 0) 
                && (errno == EINTR));         /* wait for data or connection */
        if (n < 0) {                          /* on real error exit */
        while ( ((n = select(max_fd + 1, &fset, NULL, NULL, NULL)) < 0) 
                && (errno == EINTR));         /* wait for data or connection */
        if (n < 0) {                          /* on real error exit */
            fd_open[fd] = 1;                  /* set new connection socket */
            if (max_fd < fd) max_fd = fd;     /* if needed set new maximum */
        }
            fd_open[fd] = 1;                  /* set new connection socket */
            if (max_fd < fd) max_fd = fd;     /* if needed set new maximum */
        }
-       /* loop on open connections */
-       i = list_fd;                  /* first socket to look */
-       while (n != 0) {              /* loop until active */
-           i++;                      /* start after listening socket */
+       i = list_fd;      /* first socket to look */
+       while (n != 0) {  /* loop on open connections */
+           i++;                             /* start after listening socket */
            if (fd_open[i] == 0) continue;   /* closed, go next */
            if (FD_ISSET(i, &fset)) {        /* if active process it*/
                n--;                         /* decrease active */
            if (fd_open[i] == 0) continue;   /* closed, go next */
            if (FD_ISSET(i, &fset)) {        /* if active process it*/
                n--;                         /* decrease active */
index 13ce5572a189046cfcfe3da7826976103c60350d..27361879e79dadd931019f4f2b42d469e6e8131f 100644 (file)
@@ -4241,6 +4241,10 @@ elenco, che illustra quelle attualmente disponibili:\footnote{si fa
 % http://lwn.net/Articles/531498/
 
 
 % http://lwn.net/Articles/531498/
 
 
+% TODO trattare le funzioni di protezione della memoria pkey_alloc, pkey_free,
+% pkey_mprotect, introdotte con il kernel 4.8, vedi
+% http://lwn.net/Articles/689395/ e Documentation/x86/protection-keys.txt 
+
 %TODO trattare kcmp aggiunta con il kernel 3.5, vedi
 % https://lwn.net/Articles/478111/
 
 %TODO trattare kcmp aggiunta con il kernel 3.5, vedi
 % https://lwn.net/Articles/478111/
 
index 6561859ff0a46c3d7e5673f78fb286443b60898c..aa5a3b3b1e24ccd039997a8280ceb6b4affd7dfa 100644 (file)
@@ -2490,6 +2490,7 @@ Da fare.
 
 Qui vanno spiegati i terminali virtuali, \file{/dev/pty} e compagnia.
 % vedi man pts
 
 Qui vanno spiegati i terminali virtuali, \file{/dev/pty} e compagnia.
 % vedi man pts
+% vedi 
 
 
 \subsection{Allocazione dei terminali virtuali}
 
 
 \subsection{Allocazione dei terminali virtuali}
@@ -2500,6 +2501,8 @@ Qui vanno le cose su \func{openpty} e compagnia.
 % TODO le ioctl dei terminali (man tty_ioctl)
 % e http://www.net-security.org/article.php?id=83
 % TODO trattare \func{posix\_openpt}
 % TODO le ioctl dei terminali (man tty_ioctl)
 % e http://www.net-security.org/article.php?id=83
 % TODO trattare \func{posix\_openpt}
+% vedi http://lwn.net/Articles/688809/,
+% http://man7.org/linux/man-pages/man3/ptsname.3.html
 
 
 % TODO materiale sulle seriali
 
 
 % TODO materiale sulle seriali
index 44bb3a1f04b4feee4d6165be4eb7682ebf03a681..6ce42016041f73a4752eb096d2627fc4f5f5aae6 100644 (file)
@@ -35,18 +35,17 @@ porte o altre proprietà del sistema.
 \subsection{La struttura del \textit{resolver}}
 \label{sec:sock_resolver}
 
 \subsection{La struttura del \textit{resolver}}
 \label{sec:sock_resolver}
 
-\itindbeg{resolver}
-La risoluzione dei nomi è associata tradizionalmente al servizio del
-\textit{Domain Name Service} che permette di identificare le macchine su
-internet invece che per numero IP attraverso il relativo \textsl{nome a
-  dominio}.\footnote{non staremo ad entrare nei dettagli della definizione di
-  cosa è un nome a dominio, dandolo per noto, una introduzione alla
-  problematica si trova in \cite{AGL} (cap.~9) mentre per una trattazione
-  approfondita di tutte le problematiche relative al DNS si può fare
-  riferimento a \cite{DNSbind}.} In realtà per DNS si intendono spesso i
-server che forniscono su internet questo servizio, mentre nel nostro caso
-affronteremo la problematica dal lato client, di un qualunque programma che
-necessita di compiere questa operazione.
+\itindbeg{resolver} La risoluzione dei nomi è associata tradizionalmente al
+servizio del \itindex{Domain~Name~Service} \textit{Domain Name Service} che
+permette di identificare le macchine su internet invece che per numero IP
+attraverso il relativo \textsl{nome a dominio}.\footnote{non staremo ad
+  entrare nei dettagli della definizione di cosa è un nome a dominio, dandolo
+  per noto, una introduzione alla problematica si trova in \cite{AGL} (cap.~9)
+  mentre per una trattazione approfondita di tutte le problematiche relative
+  al DNS si può fare riferimento a \cite{DNSbind}.} In realtà per DNS si
+intendono spesso i server che forniscono su internet questo servizio, mentre
+nel nostro caso affronteremo la problematica dal lato client, di un qualunque
+programma che necessita di compiere questa operazione.
 
 \begin{figure}[!htb]
   \centering \includegraphics[width=11cm]{img/resolver}
 
 \begin{figure}[!htb]
   \centering \includegraphics[width=11cm]{img/resolver}
@@ -106,32 +105,34 @@ NIS,\footnote{il \textit{Network Information Service} è un servizio, creato da
   \textit{netgroup}) varie macchine, centralizzando i servizi di definizione
   di utenti e gruppi e di autenticazione, oggi è sempre più spesso sostituito
   da LDAP.} o come quelli dei protocolli e dei servizi che sono mantenuti nei
   \textit{netgroup}) varie macchine, centralizzando i servizi di definizione
   di utenti e gruppi e di autenticazione, oggi è sempre più spesso sostituito
   da LDAP.} o come quelli dei protocolli e dei servizi che sono mantenuti nei
-file statici \conffile{/etc/protocols} e \conffile{/etc/services}.  Molte di
-queste informazioni non si trovano su un DNS, ma in una rete locale può essere
-molto utile centralizzare il mantenimento di alcune di esse su opportuni
-server.  Inoltre l'uso di diversi supporti possibili per le stesse
+file statici \conffile{/etc/protocols} e \conffile{/etc/services}.  
+
+Molte di queste informazioni non si trovano su un DNS, ma in una rete locale
+può essere molto utile centralizzare il mantenimento di alcune di esse su
+opportuni server.  Inoltre l'uso di diversi supporti possibili per le stesse
 informazioni (ad esempio il nome delle macchine può essere mantenuto sia
 tramite \conffile{/etc/hosts}, che con il DNS, che con NIS) comporta il
 informazioni (ad esempio il nome delle macchine può essere mantenuto sia
 tramite \conffile{/etc/hosts}, che con il DNS, che con NIS) comporta il
-problema dell'ordine in cui questi vengono interrogati.\footnote{con le
-  implementazioni classiche i vari supporti erano introdotti modificando
-  direttamente le funzioni di libreria, prevedendo un ordine di interrogazione
-  predefinito e non modificabile (a meno di una ricompilazione delle librerie
-  stesse).}
+problema dell'ordine in cui questi vengono interrogati. Con le implementazioni
+classiche i vari supporti erano introdotti modificando direttamente le
+funzioni di libreria, prevedendo un ordine di interrogazione predefinito e non
+modificabile (a meno di una ricompilazione delle librerie stesse).
+
+\itindbeg{Name~Service~Switch~(NSS)} 
 
 
-\itindbeg{Name~Service~Switch~(NSS)}
 Per risolvere questa serie di problemi la risoluzione dei nomi a dominio
 Per risolvere questa serie di problemi la risoluzione dei nomi a dominio
-eseguirà dal \textit{resolver} è stata inclusa all'interno di un meccanismo
+eseguità dal \textit{resolver} è stata inclusa all'interno di un meccanismo
 generico per la risoluzione di corrispondenze fra nomi ed informazioni ad essi
 generico per la risoluzione di corrispondenze fra nomi ed informazioni ad essi
-associate chiamato \textit{Name Service Switch}\footnote{il sistema è stato
-  introdotto la prima volta nelle librerie standard di Solaris, le \acr{glibc}
-  hanno ripreso lo stesso schema, si tenga presente che questo sistema non
-  esiste per altre librerie standard come le \acr{libc5} o le \acr{uclib}.}
-cui abbiamo accennato anche in sez.~\ref{sec:sys_user_group} per quanto
-riguarda la gestione dei dati associati a utenti e gruppi.  Il \textit{Name
-  Service Switch} (cui spesso si fa riferimento con l'acronimo NSS) è un
-sistema di librerie dinamiche che permette di definire in maniera generica sia
-i supporti su cui mantenere i dati di corrispondenza fra nomi e valori
-numerici, sia l'ordine in cui effettuare le ricerche sui vari supporti
+associate chiamato \textit{Name Service Switch} cui abbiamo accennato anche in
+sez.~\ref{sec:sys_user_group} per quanto riguarda la gestione dei dati
+associati a utenti e gruppi. Il sistema è stato introdotto la prima volta
+nelle librerie standard di Solaris e le \acr{glibc} hanno ripreso lo stesso
+schema; si tenga presente che questo sistema non esiste per altre librerie
+standard come le \acr{libc5} o le \acr{uclib}.
+
+Il \textit{Name Service Switch} (cui spesso si fa riferimento con l'acronimo
+NSS) è un sistema di librerie dinamiche che permette di definire in maniera
+generica sia i supporti su cui mantenere i dati di corrispondenza fra nomi e
+valori numerici, sia l'ordine in cui effettuare le ricerche sui vari supporti
 disponibili. Il sistema prevede una serie di possibili classi di
 corrispondenza, quelle attualmente definite sono riportate in
 tab.~\ref{tab:sys_NSS_classes}.
 disponibili. Il sistema prevede una serie di possibili classi di
 corrispondenza, quelle attualmente definite sono riportate in
 tab.~\ref{tab:sys_NSS_classes}.
@@ -176,14 +177,11 @@ tab.~\ref{tab:sys_NSS_classes}.
 % TODO rivedere meglio la tabella
 
 Il sistema del \textit{Name Service Switch} è controllato dal contenuto del
 % TODO rivedere meglio la tabella
 
 Il sistema del \textit{Name Service Switch} è controllato dal contenuto del
-file \conffile{/etc/nsswitch.conf}; questo contiene una riga\footnote{seguendo
-  una convezione comune per i file di configurazione le righe vuote vengono
-  ignorate e tutto quello che segue un carattere ``\texttt{\#}'' viene
-  considerato un commento.} di configurazione per ciascuna di queste classi,
-che viene inizia col nome di tab.~\ref{tab:sys_NSS_classes} seguito da un
-carattere ``\texttt{:}'' e prosegue con la lista dei \textsl{servizi} su cui
-le relative informazioni sono raggiungibili, scritti nell'ordine in cui si
-vuole siano interrogati.
+file \conffile{/etc/nsswitch.conf}; questo contiene una riga di configurazione
+per ciascuna di queste classi, che viene inizia col nome di
+tab.~\ref{tab:sys_NSS_classes} seguito da un carattere ``\texttt{:}'' e
+prosegue con la lista dei \textsl{servizi} su cui le relative informazioni
+sono raggiungibili, scritti nell'ordine in cui si vuole siano interrogati.
 
 Ogni servizio è specificato a sua volta da un nome, come \texttt{file},
 \texttt{dns}, \texttt{db}, ecc.  che identifica la libreria dinamica che
 
 Ogni servizio è specificato a sua volta da un nome, come \texttt{file},
 \texttt{dns}, \texttt{db}, ecc.  che identifica la libreria dinamica che
@@ -194,12 +192,13 @@ implementa le funzioni.
 
 In ogni caso, qualunque sia la modalità con cui ricevono i dati o il supporto
 su cui vengono mantenuti, e che si usino o meno funzionalità aggiuntive
 
 In ogni caso, qualunque sia la modalità con cui ricevono i dati o il supporto
 su cui vengono mantenuti, e che si usino o meno funzionalità aggiuntive
-fornire dal sistema del \textit{Name Service Switch}, dal punto di vista di un
+fornite dal sistema del \textit{Name Service Switch}, dal punto di vista di un
 programma che deve effettuare la risoluzione di un nome a dominio, tutto
 quello che conta sono le funzioni classiche che il \textit{resolver} mette a
 programma che deve effettuare la risoluzione di un nome a dominio, tutto
 quello che conta sono le funzioni classiche che il \textit{resolver} mette a
-disposizione,\footnote{è cura della implementazione fattane nelle \acr{glibc}
-  tenere conto della presenza del \textit{Name Service Switch}.} e sono queste
-quelle che tratteremo nelle sezioni successive.
+disposizione (è cura delle \acr{glibc} tenere conto della presenza del
+\textit{Name Service Switch}) e sono queste quelle che tratteremo nelle
+sezioni successive.  
+
 \itindend{Name~Service~Switch~(NSS)}
 
 
 \itindend{Name~Service~Switch~(NSS)}
 
 
@@ -207,14 +206,15 @@ quelle che tratteremo nelle sezioni successive.
 \label{sec:sock_resolver_functions}
 
 Prima di trattare le funzioni usate normalmente nella risoluzione dei nomi a
 \label{sec:sock_resolver_functions}
 
 Prima di trattare le funzioni usate normalmente nella risoluzione dei nomi a
-dominio conviene trattare in maniera più dettagliata il meccanismo principale
-da esse utilizzato e cioè quello del servizio DNS. Come accennato questo,
-benché in teoria sia solo uno dei possibili supporti su cui mantenere le
-informazioni, in pratica costituisce il meccanismo principale con cui vengono
-risolti i nomi a dominio.  Per questo motivo esistono una serie di funzioni di
-libreria che servono specificamente ad eseguire delle interrogazioni verso un
-server DNS, funzioni che poi vengono utilizzate per realizzare le funzioni
-generiche di libreria usate anche dal sistema del \textit{resolver}.
+dominio conviene trattare in maniera più dettagliata il servizio DNS. Come
+accennato questo, benché esso in teoria sia solo uno dei possibili supporti su
+cui mantenere le informazioni, in pratica costituisce il meccanismo principale
+con cui vengono risolti i nomi a dominio. Inolte esso può fornire anche
+ulteriori informazioni oltre relative alla risoluzione dei nomi a dominio.
+Per questo motivo esistono una serie di funzioni di libreria che servono
+specificamente ad eseguire delle interrogazioni verso un server DNS, funzioni
+che poi vengono utilizzate anche per realizzare le funzioni generiche di
+libreria usate dal sistema del \textit{resolver}.
 
 Il sistema del DNS è in sostanza di un database distribuito organizzato in
 maniera gerarchica, i dati vengono mantenuti in tanti server distinti ciascuno
 
 Il sistema del DNS è in sostanza di un database distribuito organizzato in
 maniera gerarchica, i dati vengono mantenuti in tanti server distinti ciascuno
@@ -235,33 +235,36 @@ per un suo dominio di secondo livello ad un altro server, il quale a sua volta
 potrà delegare la risoluzione di un eventuale sotto-dominio di terzo livello ad
 un altro server ancora.
 
 potrà delegare la risoluzione di un eventuale sotto-dominio di terzo livello ad
 un altro server ancora.
 
-In realtà un server DNS è in grado di fare altro rispetto alla risoluzione di
-un nome a dominio in un indirizzo IP; ciascuna voce nel database viene
-chiamata \textit{resource record}, e può contenere diverse informazioni. In
-genere i \textit{resource record} vengono classificati per la \textsl{classe
-  di indirizzi} cui i dati contenuti fanno riferimento, e per il \textsl{tipo}
-di questi ultimi.\footnote{ritroveremo classi di indirizzi e tipi di record
-  più avanti in tab.~\ref{tab:DNS_address_class} e
-  tab.~\ref{tab:DNS_record_type}.}  Oggigiorno i dati mantenuti nei server DNS
+Come accennato un server DNS è in grado di fare molto altro rispetto alla
+risoluzione di un nome a dominio in un indirizzo IP: ciascuna voce nel
+database viene chiamata \textit{resource record}, e può contenere diverse
+informazioni. In genere i \textit{resource record} vengono classificati per la
+\textsl{classe di indirizzi} cui i dati contenuti fanno riferimento, e per il
+\textsl{tipo} di questi ultimi (ritroveremo classi di indirizzi e tipi di
+record più avanti in tab.~\ref{tab:DNS_address_class} e
+tab.~\ref{tab:DNS_record_type}).  Oggigiorno i dati mantenuti nei server DNS
 sono quasi esclusivamente relativi ad indirizzi internet, per cui in pratica
 viene utilizzata soltanto una classe di indirizzi; invece le corrispondenze
 fra un nome a dominio ed un indirizzo IP sono solo uno fra i vari tipi di
 informazione che un server DNS fornisce normalmente.
 
 L'esistenza di vari tipi di informazioni è un altro dei motivi per cui il
 sono quasi esclusivamente relativi ad indirizzi internet, per cui in pratica
 viene utilizzata soltanto una classe di indirizzi; invece le corrispondenze
 fra un nome a dominio ed un indirizzo IP sono solo uno fra i vari tipi di
 informazione che un server DNS fornisce normalmente.
 
 L'esistenza di vari tipi di informazioni è un altro dei motivi per cui il
-\textit{resolver} prevede, rispetto a quelle relative alla semplice
-risoluzione dei nomi, un insieme di funzioni specifiche dedicate
-all'interrogazione di un server DNS; la prima di queste funzioni è
-\funcd{res\_init}, il cui prototipo è:
-\begin{functions}
-  \headdecl{netinet/in.h} \headdecl{arpa/nameser.h} \headdecl{resolv.h}
-  \funcdecl{int res\_init(void)}
-
-Inizializza il sistema del \textit{resolver}.
+\textit{resolver} prevede, oltre a quelle relative alla semplice risoluzione
+dei nomi, un insieme di funzioni specifiche dedicate all'interrogazione di un
+server DNS, tutte nella forma \texttt{res\_}\textsl{\texttt{nome}}.
+Tradizionalmente la prima di queste funzioni è \funcd{res\_init}, il cui
+prototipo è:
 
 
-\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
-  errore.}
-\end{functions}
+\begin{funcproto}{
+\fhead{netinet/in.h} 
+\fhead{arpa/nameser.h} 
+\fhead{resolv.h}
+\fdecl{int res\_init(void)}
+\fdesc{Inizializza il sistema del \textit{resolver}.} 
+}
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore.
+}
+\end{funcproto}
 
 La funzione legge il contenuto dei file di configurazione (i già citati
 \file{resolv.conf} e \file{host.conf}) per impostare il dominio di default,
 
 La funzione legge il contenuto dei file di configurazione (i già citati
 \file{resolv.conf} e \file{host.conf}) per impostare il dominio di default,
@@ -273,20 +276,48 @@ ambiente \envvar{LOCALDOMAIN}). In genere non è necessario eseguire questa
 funzione direttamente in quanto viene automaticamente chiamata la prima volta
 che si esegue una delle altre.
 
 funzione direttamente in quanto viene automaticamente chiamata la prima volta
 che si esegue una delle altre.
 
-Le impostazioni e lo stato del \textit{resolver} vengono mantenuti in una
-serie di variabili raggruppate nei campi di una apposita struttura \var{\_res}
-usata da tutte queste funzioni. Essa viene definita in \headfiled{resolv.h} ed
-è utilizzata internamente alle funzioni essendo definita come variabile
-globale; questo consente anche di accedervi direttamente all'interno di un
-qualunque programma, una volta che la sia opportunamente dichiarata come:
+Le impostazioni e lo stato del \textit{resolver} inizializzati da
+\func{res\_init} vengono mantenuti in una serie di variabili raggruppate nei
+campi di una apposita struttura \var{\_res} usata da tutte queste
+funzioni. Essa viene definita in \headfiled{resolv.h} ed è utilizzata
+internamente alle funzioni essendo definita come variabile globale; questo
+consente anche di accedervi direttamente all'interno di un qualunque
+programma, una volta che la sia opportunamente dichiarata come:
 \includecodesnip{listati/resolv_option.c}
 
 \includecodesnip{listati/resolv_option.c}
 
-Tutti i campi della struttura sono ad uso interno, e vengono usualmente
-inizializzati da \func{res\_init} in base al contenuto dei file di
+Dato che l'uso di una variabile globale rende tutte le funzioni classiche non
+rientranti, con l'uscita di BIND 8.2 è stata introdotta una nuova interfaccia
+in cui tutte le nuove funzioni (il cui nome è ottenuto apponendo una
+``\texttt{n}'' al nome di quella tradizionale nella forma
+\texttt{res\_n\textsl{nome}}). Tutte le nuove funzioni prendono un primo
+argomento aggiuntivo, \param{statep}, che punti ad una struttura dello stesso
+tipo, che verrà usato per mantenere lo stato del \textit{resolver} e potrà
+essere usata senza problemi anche con programmi \textit{multithread}.  Anche
+in questo caso per poterlo utilizzare occorrerà una opportuna dichiarazione
+del tipo di dato con:
+\includecodesnip{listati/resolv_newoption.c}
+e la nuova funzione che utilizzata per inizializzare il \textit{resolver} (che
+come la precedente viene chiamata automaticamente dalle altre funzioni) è
+\funcd{res\_ninit} il cui prototipo è:
+
+\begin{funcproto}{
+\fhead{netinet/in.h} 
+\fhead{arpa/nameser.h} 
+\fhead{resolv.h}
+\fdecl{int res\_ninit(res\_state statep)}
+\fdesc{Inizializza il sistema del \textit{resolver}.} 
+}
+{La funzione ritorna $0$ in caso di successo e $-1$ per un errore.
+}
+\end{funcproto}
+
+Indipendentemente da quale versione delle funzioni si usino, tutti i campi
+della struttura sono ad uso interno, e vengono usualmente inizializzate da
+\func{res\_init} o \func{res\_ninit} in base al contenuto dei file di
 configurazione e ad una serie di valori di default. L'unico campo che può
 essere utile modificare è \var{\_res.options}, una maschera binaria che
 contiene una serie di bit di opzione che permettono di controllare il
 configurazione e ad una serie di valori di default. L'unico campo che può
 essere utile modificare è \var{\_res.options}, una maschera binaria che
 contiene una serie di bit di opzione che permettono di controllare il
-comportamento del \textit{resolver}. 
+comportamento del \textit{resolver}.
 
 \begin{table}[htb]
   \centering
 
 \begin{table}[htb]
   \centering
@@ -359,34 +390,37 @@ di ambiente come abbiamo visto per \envvar{LOCALDOMAIN}. In particolare con
 controlla quante volte viene ripetuto il tentativo di connettersi ad un server
 DNS prima di dichiarare fallimento; il valore di default è 4, un valore nullo
 significa bloccare l'uso del DNS. Infine con \envvar{RES\_TIMEOUT} si
 controlla quante volte viene ripetuto il tentativo di connettersi ad un server
 DNS prima di dichiarare fallimento; il valore di default è 4, un valore nullo
 significa bloccare l'uso del DNS. Infine con \envvar{RES\_TIMEOUT} si
-soprassiede il valore del campo \var{retrans},\footnote{preimpostato al valore
-  della omonima costante \const{RES\_TIMEOUT} di \headfile{resolv.h}.} che è
-il valore preso come base (in numero di secondi) per definire la scadenza di
-una richiesta, ciascun tentativo di richiesta fallito viene ripetuto
-raddoppiando il tempo di scadenza per il numero massimo di volte stabilito da
+soprassiede il valore del campo \var{retrans} (preimpostato al valore della
+omonima costante \const{RES\_TIMEOUT} di \headfile{resolv.h}) che è il valore
+preso come base (in numero di secondi) per definire la scadenza di una
+richiesta, ciascun tentativo di richiesta fallito viene ripetuto raddoppiando
+il tempo di scadenza per il numero massimo di volte stabilito da
 \texttt{RES\_RETRY}.
 
 \texttt{RES\_RETRY}.
 
-La funzione di interrogazione principale è \funcd{res\_query}, che serve ad
-eseguire una richiesta ad un server DNS per un nome a dominio
-\textsl{completamente specificato} (quello che si chiama
-\itindex{Fully~Qualified~Domain~Name~(FQDN)} FQDN, \textit{Fully Qualified
-  Domain Name}); il suo prototipo è:
-
-\begin{functions}
-\headdecl{netinet/in.h}
-\headdecl{arpa/nameser.h}
-\headdecl{resolv.h}
-\funcdecl{int res\_query(const char *dname, int class, int type,
+La funzione di interrogazione principale è \funcd{res\_query}
+(\funcd{res\_nquery} per la nuova interfaccia), che serve ad eseguire una
+richiesta ad un server DNS per un nome a dominio \textsl{completamente
+  specificato} (quello che si chiama
+\itindex{Fully~Qualified~Domain~Name~(FQDN)} FQDN, \textit{Fully Qualified 
+  Domain Name}); il loro prototipo è:
+
+\begin{funcproto}{
+\fhead{netinet/in.h} 
+\fhead{arpa/nameser.h} 
+\fhead{resolv.h}
+\fdecl{int res\_query(const char *dname, int class, int type,
               unsigned char *answer, int anslen)}
               unsigned char *answer, int anslen)}
+\fdecl{int res\_nquery(res\_state statep, const char *dname, int class, int
+  type, \\
+  \phantom{int res\_nquery(}unsigned char *answer, int anslen)}
+\fdesc{Esegue una interrogazione al DNS.} 
+}
+{Le funzioni ritornano un valore positivo pari alla lunghezza dei dati scritti
+  nel buffer \param{answer} in caso di successo e $-1$ per un errore.
+}
+\end{funcproto}
 
 
-  Esegue una interrogazione al DNS.
-
-\bodydesc{La funzione restituisce un valore positivo pari alla lunghezza dei
-    dati scritti nel buffer \param{answer} in caso di successo e -1 in caso di
-    errore.}
-\end{functions}
-
-La funzione esegue una interrogazione ad un server DNS relativa al nome da
+Le funzioni eseguono una interrogazione ad un server DNS relativa al nome da
 risolvere passato nella stringa indirizzata da \param{dname}, inoltre deve
 essere specificata la classe di indirizzi in cui eseguire la ricerca con
 \param{class}, ed il tipo di \textit{resource record} che si vuole ottenere
 risolvere passato nella stringa indirizzata da \param{dname}, inoltre deve
 essere specificata la classe di indirizzi in cui eseguire la ricerca con
 \param{class}, ed il tipo di \textit{resource record} che si vuole ottenere
@@ -394,34 +428,38 @@ con \param{type}. Il risultato della ricerca verrà scritto nel buffer di
 lunghezza \param{anslen} puntato da \param{answer} che si sarà opportunamente
 allocato in precedenza.
 
 lunghezza \param{anslen} puntato da \param{answer} che si sarà opportunamente
 allocato in precedenza.
 
-
-Una seconda funzione di ricerca, analoga a \func{res\_query}, che prende gli
-stessi argomenti, ma che esegue l'interrogazione con le funzionalità
+Una seconda funzione di ricerca analoga a \func{res\_query}, che prende gli
+stessi argomenti ma che esegue l'interrogazione con le funzionalità
 addizionali previste dalle due opzioni \const{RES\_DEFNAMES} e
 addizionali previste dalle due opzioni \const{RES\_DEFNAMES} e
-\const{RES\_DNSRCH}, è \funcd{res\_search}, il cui prototipo è:
-\begin{functions}
-\headdecl{netinet/in.h}
-\headdecl{arpa/nameser.h}
-\headdecl{resolv.h}
-\funcdecl{int res\_search(const char *dname, int class, int type,
-              unsigned char *answer, int anslen)}
-
-  Esegue una interrogazione al DNS.
-  
-  \bodydesc{La funzione restituisce un valore positivo pari alla lunghezza dei
-    dati scritti nel buffer \param{answer} in caso di successo e -1 in caso di
-    errore.}
-\end{functions}
+\const{RES\_DNSRCH}, è \funcd{res\_search} (\funcd{res\_nsearch} per la nuova
+interfaccia), il cui prototipo è:
+
+\begin{funcproto}{
+\fhead{netinet/in.h} 
+\fhead{arpa/nameser.h} 
+\fhead{resolv.h}
+\fdecl{int res\_search(const char *dname, int class, int type,
+  unsigned char *answer, \\
+  \phantom{int res\_search}int anslen)}
+\fdecl{int res\_nsearch(res\_state statep, const char *dname, int class, 
+  int type, \\
+  \phantom{int res\_nsearch(}unsigned char *answer, int anslen)}
+\fdesc{Esegue una interrogazione al DNS.} 
+}
+{Le funzioni ritornano un valore positivo pari alla lunghezza dei dati scritti
+  nel buffer \param{answer} in caso di successo e $-1$ per un errore.
+}
+\end{funcproto}
 
 In sostanza la funzione ripete una serie di chiamate a \func{res\_query}
 
 In sostanza la funzione ripete una serie di chiamate a \func{res\_query}
-aggiungendo al nome contenuto nella stringa \param{dname} il dominio di
-default da cercare, fermandosi non appena trova un risultato.  Il risultato di
-entrambe le funzioni viene scritto nel formato opportuno (che sarà diverso a
-seconda del tipo di record richiesto) nel buffer di ritorno; sarà compito del
-programma (o di altre funzioni) estrarre i relativi dati, esistono una serie
-di funzioni interne usate per la scansione di questi dati, per chi fosse
-interessato una trattazione dettagliata è riportata nel quattordicesimo
-capitolo di \cite{DNSbind}.
+(\func{res\_nquery}) aggiungendo al nome contenuto nella stringa \param{dname}
+il dominio di default da cercare, fermandosi non appena trova un risultato.
+Il risultato di entrambe le funzioni viene scritto nel formato opportuno (che
+sarà diverso a seconda del tipo di record richiesto) nel buffer di ritorno;
+sarà compito del programma (o di altre funzioni) estrarre i relativi dati,
+esistono una serie di funzioni interne usate per la scansione di questi dati,
+per chi fosse interessato una trattazione dettagliata è riportata nel
+quattordicesimo capitolo di \cite{DNSbind}.
 
 Le classi di indirizzi supportate da un server DNS sono tre, ma di queste in
 pratica oggi viene utilizzata soltanto quella degli indirizzi internet; le
 
 Le classi di indirizzi supportate da un server DNS sono tre, ma di queste in
 pratica oggi viene utilizzata soltanto quella degli indirizzi internet; le
index 8593a42d4d67c1cf7be29c727d2a31eb4a0e016a..8e64ed513b109b61b1c12bc8290e7b4ab2b49202 100644 (file)
@@ -3226,7 +3226,7 @@ che errori relativi alla stessa linea non vengano ripetuti.
 % LocalWords:  newlen ENOTDIR EINVAL ENOMEM linux array oldvalue paging stack
 % LocalWords:  TCP shell Documentation ostype hostname osrelease version mount
 % LocalWords:  const source filesystemtype mountflags ENODEV ENOTBLK block read
 % LocalWords:  newlen ENOTDIR EINVAL ENOMEM linux array oldvalue paging stack
 % LocalWords:  TCP shell Documentation ostype hostname osrelease version mount
 % LocalWords:  const source filesystemtype mountflags ENODEV ENOTBLK block read
-% LocalWords:  device EBUSY only EACCES NODEV ENXIO major RTSIG syscall PID NSS
+% LocalWords:  device EBUSY only EACCES NODEV ENXIO major RTSIG syscall PID 
 % LocalWords:  number EMFILE dummy ENAMETOOLONG ENOENT ELOOP virtual devfs MGC
 % LocalWords:  magic MSK RDONLY NOSUID suid sgid NOEXEC SYNCHRONOUS REMOUNT MNT
 % LocalWords:  MANDLOCK mandatory locking WRITE APPEND append IMMUTABLE NOATIME
 % LocalWords:  number EMFILE dummy ENAMETOOLONG ENOENT ELOOP virtual devfs MGC
 % LocalWords:  magic MSK RDONLY NOSUID suid sgid NOEXEC SYNCHRONOUS REMOUNT MNT
 % LocalWords:  MANDLOCK mandatory locking WRITE APPEND append IMMUTABLE NOATIME
index d6b5a945f216475483d1b44356e1004d708a5aa8..8a7b5e794a5c8ceae62757c8b360e13320c8c3a7 100644 (file)
@@ -3414,8 +3414,8 @@ disponibile coi sorgenti allegati nel file \texttt{select\_echod.c}.
     \includecodesample{listati/select_echod.c}
   \end{minipage} 
   \normalsize
     \includecodesample{listati/select_echod.c}
   \end{minipage} 
   \normalsize
-  \caption{La sezione principale del codice della nuova versione di server
-    \textit{echo} basati sull'uso della funzione \func{select}.}
+  \caption{La sezione principale della nuova versione di server
+    \textit{echo} basato sull'uso della funzione \func{select}.}
   \label{fig:TCP_SelectEchod}
 \end{figure}
 
   \label{fig:TCP_SelectEchod}
 \end{figure}
 
@@ -3427,7 +3427,7 @@ tabella dei socket connessi mantenuta nel vettore \var{fd\_open} dimensionato
 al valore di \const{FD\_SETSIZE}, ed una variabile \var{max\_fd} per
 registrare il valore più alto dei file descriptor aperti.
 
 al valore di \const{FD\_SETSIZE}, ed una variabile \var{max\_fd} per
 registrare il valore più alto dei file descriptor aperti.
 
-Prima di entrare nel ciclo principale (\texttt{\small 6--56}) la nostra
+Prima di entrare nel ciclo principale (\texttt{\small 5--53}) la nostra
 tabella viene inizializzata (\texttt{\small 2}) a zero (valore che
 utilizzeremo come indicazione del fatto che il relativo file descriptor non è
 aperto), mentre il valore massimo (\texttt{\small 3}) per i file descriptor
 tabella viene inizializzata (\texttt{\small 2}) a zero (valore che
 utilizzeremo come indicazione del fatto che il relativo file descriptor non è
 aperto), mentre il valore massimo (\texttt{\small 3}) per i file descriptor
@@ -3435,23 +3435,23 @@ aperti viene impostato a quello del socket in ascolto, in quanto esso è
 l'unico file aperto, oltre i tre standard, e pertanto avrà il valore più alto,
 che verrà anche (\texttt{\small 4}) inserito nella tabella.
 
 l'unico file aperto, oltre i tre standard, e pertanto avrà il valore più alto,
 che verrà anche (\texttt{\small 4}) inserito nella tabella.
 
-La prima sezione (\texttt{\small 7--10}) del ciclo principale esegue la
+La prima sezione (\texttt{\small 6--8}) del ciclo principale esegue la
 costruzione del \textit{file descriptor set} \var{fset} in base ai socket
 connessi in un certo momento; all'inizio ci sarà soltanto il socket in ascolto
 ma nel prosieguo delle operazioni verranno utilizzati anche tutti i socket
 connessi registrati nella tabella \var{fd\_open}.  Dato che la chiamata di
 \func{select} modifica il valore del \textit{file descriptor set} è necessario
 costruzione del \textit{file descriptor set} \var{fset} in base ai socket
 connessi in un certo momento; all'inizio ci sarà soltanto il socket in ascolto
 ma nel prosieguo delle operazioni verranno utilizzati anche tutti i socket
 connessi registrati nella tabella \var{fd\_open}.  Dato che la chiamata di
 \func{select} modifica il valore del \textit{file descriptor set} è necessario
-ripetere (\texttt{\small 7}) ogni volta il suo azzeramento per poi procedere
-con il ciclo (\texttt{\small 8--10}) in cui si impostano i socket trovati
+ripetere (\texttt{\small 6}) ogni volta il suo azzeramento per poi procedere
+con il ciclo (\texttt{\small 7--8}) in cui si impostano i socket trovati
 attivi.
 
 Per far questo si usa la caratteristica dei file descriptor, descritta in
 sez.~\ref{sec:file_open_close}, per cui il kernel associa sempre ad ogni nuovo
 file il file descriptor con il valore più basso disponibile. Questo fa sì che
 attivi.
 
 Per far questo si usa la caratteristica dei file descriptor, descritta in
 sez.~\ref{sec:file_open_close}, per cui il kernel associa sempre ad ogni nuovo
 file il file descriptor con il valore più basso disponibile. Questo fa sì che
-si possa eseguire il ciclo (\texttt{\small 8}) a partire da un valore minimo,
+si possa eseguire il ciclo (\texttt{\small 7}) a partire da un valore minimo,
 che sarà sempre quello del socket in ascolto, mantenuto in \var{list\_fd},
 fino al valore massimo di \var{max\_fd} che dovremo aver cura di tenere
 che sarà sempre quello del socket in ascolto, mantenuto in \var{list\_fd},
 fino al valore massimo di \var{max\_fd} che dovremo aver cura di tenere
-aggiornato.  Dopo di che basterà controllare (\texttt{\small 9}) nella nostra
+aggiornato.  Dopo di che basterà controllare (\texttt{\small 8}) nella nostra
 tabella se il file descriptor è in uso o meno,\footnote{si tenga presente che
   benché il kernel assegni sempre il primo valore libero, si potranno sempre
   avere dei \textsl{buchi} nella nostra tabella dato che nelle operazioni i
 tabella se il file descriptor è in uso o meno,\footnote{si tenga presente che
   benché il kernel assegni sempre il primo valore libero, si potranno sempre
   avere dei \textsl{buchi} nella nostra tabella dato che nelle operazioni i
@@ -3462,64 +3462,65 @@ Una volta inizializzato con i socket aperti il nostro \textit{file descriptor
   set} potremo chiamare \func{select} per fargli osservare lo stato degli
 stessi (in lettura, presumendo che la scrittura sia sempre consentita). Come
 per il precedente esempio di sez.~\ref{sec:TCP_child_hand}, essendo questa
   set} potremo chiamare \func{select} per fargli osservare lo stato degli
 stessi (in lettura, presumendo che la scrittura sia sempre consentita). Come
 per il precedente esempio di sez.~\ref{sec:TCP_child_hand}, essendo questa
-l'unica funzione che può bloccarsi, ed essere interrotta da un segnale, la
-eseguiremo (\texttt{\small 11--12}) all'interno di un ciclo di \code{while}
+l'unica funzione che può bloccarsi ed essere interrotta da un segnale, la
+eseguiremo (\texttt{\small 9--10}) all'interno di un ciclo di \code{while},
 che la ripete indefinitamente qualora esca con un errore di \errcode{EINTR}.
 che la ripete indefinitamente qualora esca con un errore di \errcode{EINTR}.
-Nel caso invece di un errore normale si provvede (\texttt{\small 13--16}) ad
-uscire stampando un messaggio di errore.
-
-Se invece la funzione ritorna normalmente avremo in \var{n} il numero di
-socket da controllare. Nello specifico si danno due possibili casi diversi per
-cui \func{select} può essere ritornata: o si è ricevuta una nuova connessione
-ed è pronto il socket in ascolto, sul quale si può eseguire \func{accept}, o
-c'è attività su uno dei socket connessi, sui quali si può eseguire
-\func{read}.
-
-Il primo caso viene trattato immediatamente (\texttt{\small 17--26}): si
-controlla (\texttt{\small 17}) che il socket in ascolto sia fra quelli attivi,
-nel qual caso anzitutto (\texttt{\small 18}) se ne decrementa il numero in
-\var{n}. Poi, inizializzata (\texttt{\small 19}) la lunghezza della struttura
-degli indirizzi, si esegue \func{accept} per ottenere il nuovo socket connesso
-controllando che non ci siano errori (\texttt{\small 20--23}). In questo caso
-non c'è più la necessità di controllare per interruzioni dovute a segnali, in
-quanto siamo sicuri che \func{accept} non si bloccherà. Per completare la
-trattazione occorre a questo punto aggiungere (\texttt{\small 24}) il nuovo
-file descriptor alla tabella di quelli connessi, ed inoltre, se è il caso,
-aggiornare (\texttt{\small 25}) il valore massimo in \var{max\_fd}.
+Nel caso invece di un errore normale si provvede (\texttt{\small 11--14}) ad
+uscire dal programma stampando un messaggio di errore.
+
+Infine quando la funzione ritorna normalmente avremo in \var{n} il numero di
+socket da controllare. Nello specifico si danno due casi per cui \func{select}
+può ritornare: o si è ricevuta una nuova connessione ed è pronto il socket in
+ascolto, sul quale si può eseguire \func{accept}, o c'è attività su uno dei
+socket connessi, sui quali si può eseguire \func{read}.
+
+Il primo caso viene trattato immediatamente (\texttt{\small 15--24}): si
+controlla (\texttt{\small 15}) che il socket in ascolto sia fra quelli attivi,
+nel qual caso anzitutto (\texttt{\small 16}) se ne decrementa il numero
+mantenuto nella variabile \var{n}. Poi, inizializzata (\texttt{\small 17}) la
+lunghezza della struttura degli indirizzi, si esegue \func{accept} per
+ottenere il nuovo socket connesso, controllando che non ci siano errori
+(\texttt{\small 18--21}). In questo caso non c'è più la necessità di
+controllare per interruzioni dovute a segnali, in quanto siamo sicuri che
+\func{accept} non si bloccherà. Per completare la trattazione occorre a questo
+punto aggiungere (\texttt{\small 22}) il nuovo file descriptor alla tabella di
+quelli connessi, ed inoltre, se è il caso, aggiornare (\texttt{\small 23}) il
+valore massimo in \var{max\_fd}.
 
 Una volta controllato l'arrivo di nuove connessioni si passa a verificare se
 ci sono dati sui socket connessi, per questo si ripete un ciclo
 
 Una volta controllato l'arrivo di nuove connessioni si passa a verificare se
 ci sono dati sui socket connessi, per questo si ripete un ciclo
-(\texttt{\small 29--55}) fintanto che il numero di socket attivi \var{n} resta
-diverso da zero; in questo modo se l'unico socket con attività era quello
-connesso, avendo opportunamente decrementato il contatore, il ciclo verrà
-saltato e si ritornerà immediatamente, ripetuta l'inizializzazione del
-\textit{file descriptor set} con i nuovi valori nella tabella, alla chiamata
-di \func{accept}. 
+(\texttt{\small 26--52}) fintanto che il numero di socket attivi indicato
+dalla variabile \var{n} resta diverso da zero. In questo modo, se l'unico
+socket con attività era quello connesso, avendola opportunamente decrementata
+in precedenza, essa risulterà nulla, pertanto il ciclo di verifica verrà
+saltato e si ritornerà all'inzizio del ciclo principale, ripetendo, dopo
+l'inizializzazione del \textit{file descriptor set} con i nuovi valori nella
+tabella, la chiamata di \func{select}.
 
 Se il socket attivo non è quello in ascolto, o ce ne sono comunque anche
 altri, il valore di \var{n} non sarà nullo ed il controllo sarà
 
 Se il socket attivo non è quello in ascolto, o ce ne sono comunque anche
 altri, il valore di \var{n} non sarà nullo ed il controllo sarà
-eseguito. Prima di entrare nel ciclo comunque si inizializza (\texttt{\small
-  28}) il valore della variabile \var{i}, che useremo come indice nella
-tabella, \var{fd\_open} al valore minimo, corrispondente al file descriptor
-del socket in ascolto.
+eseguito. Prima di entrare nel ciclo di veridica comunque si inizializza
+(\texttt{\small 25}) il valore della variabile \var{i}, che useremo come
+indice nella tabella \var{fd\_open}, al valore minimo, corrispondente al file
+descriptor del socket in ascolto.
 
 
-Il primo passo (\texttt{\small 30}) nella verifica è incrementare il valore
+Il primo passo (\texttt{\small 27}) nella verifica è incrementare il valore
 dell'indice \var{i} per posizionarsi sul primo valore possibile per un file
 descriptor associato ad un eventuale socket connesso, dopo di che si controlla
 dell'indice \var{i} per posizionarsi sul primo valore possibile per un file
 descriptor associato ad un eventuale socket connesso, dopo di che si controlla
-(\texttt{\small 31}) se questo è nella tabella dei socket connessi, chiedendo
+(\texttt{\small 28}) se questo è nella tabella dei socket connessi, chiedendo
 la ripetizione del ciclo in caso contrario. Altrimenti si passa a verificare
 la ripetizione del ciclo in caso contrario. Altrimenti si passa a verificare
-(\texttt{\small 32}) se il file descriptor corrisponde ad uno di quelli
-attivi, e nel caso si esegue (\texttt{\small 33}) una lettura, uscendo con un
-messaggio in caso di errore (\texttt{\small 34--38}).
-
-Se (\texttt{\small 39}) il numero di byte letti \var{nread} è nullo si è in
-presenza di un \textit{end-of-file}, indice che una connessione che si è
-chiusa, che deve essere trattato (\texttt{\small 39--48}) opportunamente.  Il
-primo passo è chiudere (\texttt{\small 40}) anche il proprio capo del socket e
-rimuovere (\texttt{\small 41}) il file descriptor dalla tabella di quelli
-aperti, inoltre occorre verificare (\texttt{\small 42}) se il file descriptor
+(\texttt{\small 29}) se il file descriptor corrisponde ad uno di quelli
+attivi, e nel caso si esegue (\texttt{\small 30}) una lettura, uscendo con un
+messaggio in caso di errore (\texttt{\small 31--35}).
+
+Se (\texttt{\small 36}) il numero di byte letti \var{nread} è nullo si è in
+presenza di una \textit{end-of-file}, indice che una connessione che si è
+chiusa, che deve essere trattata (\texttt{\small 36--45}) opportunamente.  Il
+primo passo è chiudere (\texttt{\small 37}) anche il proprio capo del socket e
+rimuovere (\texttt{\small 38}) il file descriptor dalla tabella di quelli
+aperti, inoltre occorre verificare (\texttt{\small 39}) se il file descriptor
 chiuso è quello con il valore più alto, nel qual caso occorre trovare
 chiuso è quello con il valore più alto, nel qual caso occorre trovare
-(\texttt{\small 42--46}) il nuovo massimo, altrimenti (\texttt{\small 47}) si
+(\texttt{\small 39--43}) il nuovo massimo, altrimenti (\texttt{\small 44}) si
 può ripetere il ciclo da capo per esaminare (se ne restano) ulteriori file
 descriptor attivi.
 
 può ripetere il ciclo da capo per esaminare (se ne restano) ulteriori file
 descriptor attivi.
 
@@ -3527,15 +3528,15 @@ Se però è stato chiuso il file descriptor più alto, dato che la scansione dei
 file descriptor attivi viene fatta a partire dal valore più basso, questo
 significa che siamo anche arrivati alla fine della scansione, per questo
 possiamo utilizzare direttamente il valore dell'indice \var{i} con un ciclo
 file descriptor attivi viene fatta a partire dal valore più basso, questo
 significa che siamo anche arrivati alla fine della scansione, per questo
 possiamo utilizzare direttamente il valore dell'indice \var{i} con un ciclo
-all'indietro (\texttt{\small 43}) che trova il primo valore per cui la tabella
-presenta un file descriptor aperto, e lo imposta (\texttt{\small 44}) come
-nuovo massimo, per poi tornare (\texttt{\small 44}) al ciclo principale con un
+all'indietro (\texttt{\small 40}) che trova il primo valore per cui la tabella
+presenta un file descriptor aperto, e lo imposta (\texttt{\small 41}) come
+nuovo massimo, per poi tornare (\texttt{\small 42}) al ciclo principale con un
 \code{break}, e rieseguire \func{select}.
 
 Se infine si sono effettivamente letti dei dati dal socket (ultimo caso
 \code{break}, e rieseguire \func{select}.
 
 Se infine si sono effettivamente letti dei dati dal socket (ultimo caso
-rimasto) si potrà invocare immediatamente (\texttt{\small 49})
+rimasto) si potrà invocare immediatamente (\texttt{\small 46})
 \func{FullWrite} per riscriverli indietro sul socket stesso, avendo cura di
 \func{FullWrite} per riscriverli indietro sul socket stesso, avendo cura di
-uscire con un messaggio in caso di errore (\texttt{\small 50--53}). Si noti
+uscire con un messaggio in caso di errore (\texttt{\small 47--50}). Si noti
 che nel ciclo si esegue una sola lettura, contrariamente a quanto fatto con la
 precedente versione (si riveda il codice di fig.~\ref{fig:TCP_ServEcho_second})
 in cui si continuava a leggere fintanto che non si riceveva un
 che nel ciclo si esegue una sola lettura, contrariamente a quanto fatto con la
 precedente versione (si riveda il codice di fig.~\ref{fig:TCP_ServEcho_second})
 in cui si continuava a leggere fintanto che non si riceveva un
@@ -3623,8 +3624,8 @@ struttura del programma resta sostanzialmente la stessa.
     \includecodesample{listati/poll_echod.c}
   \end{minipage} 
   \normalsize
     \includecodesample{listati/poll_echod.c}
   \end{minipage} 
   \normalsize
-  \caption{La sezione principale del codice della nuova versione di server
-    \textit{echo} basati sull'uso della funzione \func{poll}.}
+  \caption{La sezione principale della nuova versione di server
+    \textit{echo} basato sull'uso della funzione \func{poll}.}
   \label{fig:TCP_PollEchod}
 \end{figure}
 
   \label{fig:TCP_PollEchod}
 \end{figure}
 
@@ -3646,8 +3647,8 @@ l'opzione \texttt{-n} ed ha un valore di default di 256.
 Dopo di che si preimposta (\texttt{\small 3}) il valore \var{max\_fd} del file
 descriptor aperto con valore più alto a quello del socket in ascolto (al
 momento l'unico), e si provvede (\texttt{\small 4--7}) ad inizializzare le
 Dopo di che si preimposta (\texttt{\small 3}) il valore \var{max\_fd} del file
 descriptor aperto con valore più alto a quello del socket in ascolto (al
 momento l'unico), e si provvede (\texttt{\small 4--7}) ad inizializzare le
-strutture, disabilitando (\texttt{\small 5}) l'osservazione con un valore
-negativo del campo \var{fd} ma predisponendo (\texttt{\small 6}) il campo
+strutture, disabilitando l'osservazione (\texttt{\small 5}) con un valore
+negativo del campo \var{fd}, ma predisponendo (\texttt{\small 6}) il campo
 \var{events} per l'osservazione dei dati normali con \const{POLLRDNORM}.
 Infine (\texttt{\small 8}) si attiva l'osservazione del socket in ascolto
 inizializzando la corrispondente struttura. Questo metodo comporta, in
 \var{events} per l'osservazione dei dati normali con \const{POLLRDNORM}.
 Infine (\texttt{\small 8}) si attiva l'osservazione del socket in ascolto
 inizializzando la corrispondente struttura. Questo metodo comporta, in
@@ -3657,59 +3658,59 @@ che non vengono mai utilizzate in quanto la prima è sempre quella relativa al
 socket in ascolto.
 
 Una volta completata l'inizializzazione tutto il lavoro viene svolto
 socket in ascolto.
 
 Una volta completata l'inizializzazione tutto il lavoro viene svolto
-all'interno del ciclo principale \texttt{\small 10--55}) che ha una struttura
+all'interno del ciclo principale \texttt{\small 9--53}) che ha una struttura
 sostanzialmente identica a quello usato per il precedente esempio basato su
 sostanzialmente identica a quello usato per il precedente esempio basato su
-\func{select}. La prima istruzione (\texttt{\small 11--12}) è quella di
-eseguire \func{poll} all'interno di un ciclo che la ripete qualora venisse
-interrotta da un segnale, da cui si esce soltanto quando la funzione ritorna,
-restituendo nella variabile \var{n} il numero di file descriptor trovati
-attivi.  Qualora invece si sia ottenuto un errore si procede (\texttt{\small
-  13--16}) alla terminazione immediata del processo provvedendo a stampare una
-descrizione dello stesso.
+\func{select}. La prima istruzione (\texttt{\small 10}) è quella di eseguire
+\func{poll} all'interno di un ciclo che la ripete qualora venisse interrotta
+da un segnale, da cui si esce soltanto quando la funzione ritorna restituendo
+nella variabile \var{n} il numero di file descriptor trovati attivi.  Qualora
+invece si sia ottenuto un errore si procede (\texttt{\small 11--14}) alla
+terminazione immediata del processo provvedendo a stampare una descrizione
+dello stesso.
 
 Una volta ottenuta dell'attività su un file descriptor si hanno di nuovo due
 
 Una volta ottenuta dell'attività su un file descriptor si hanno di nuovo due
-possibilità. La prima possibilità è che ci sia attività sul socket in ascolto,
-indice di una nuova connessione, nel qual caso si controlla (\texttt{\small
-  17}) se il campo \var{revents} della relativa struttura è attivo; se è così
-si provvede (\texttt{\small 18}) a decrementare la variabile \var{n} (che
-assume il significato di numero di file descriptor attivi rimasti da
-controllare) per poi (\texttt{\small 19--23}) effettuare la chiamata ad
-\func{accept}, terminando il processo in caso di errore. Se la chiamata ad
-\func{accept} ha successo si procede attivando (\texttt{\small 24}) la
-struttura relativa al nuovo file descriptor da essa ottenuto, modificando
-(\texttt{\small 24}) infine quando necessario il valore massimo dei file
-descriptor aperti mantenuto in \var{max\_fd}.
+possibilità. La prima è che ci sia attività sul socket in ascolto, indice di
+una nuova connessione, nel qual caso si controlla (\texttt{\small 17}) se il
+campo \var{revents} della relativa struttura è attivo; se è così si provvede
+(\texttt{\small 16}) a decrementare la variabile \var{n} (che assume il
+significato di numero di file descriptor attivi rimasti da controllare) per
+poi (\texttt{\small 17--21}) effettuare la chiamata ad \func{accept},
+terminando il processo in caso di errore. Se la chiamata ad \func{accept} ha
+successo si procede attivando (\texttt{\small 22}) la struttura relativa al
+nuovo file descriptor da essa ottenuto, modificando (\texttt{\small 23})
+infine quando necessario il valore massimo dei file descriptor aperti
+mantenuto in \var{max\_fd}.
 
 La seconda possibilità è che vi sia dell'attività su uno dei socket aperti in
 
 La seconda possibilità è che vi sia dell'attività su uno dei socket aperti in
-precedenza, nel qual caso si inizializza (\texttt{\small 27}) l'indice \var{i}
+precedenza, nel qual caso si inizializza (\texttt{\small 25}) l'indice \var{i}
 del vettore delle strutture \struct{pollfd} al valore del socket in ascolto,
 dato che gli ulteriori socket aperti avranno comunque un valore superiore.  Il
 del vettore delle strutture \struct{pollfd} al valore del socket in ascolto,
 dato che gli ulteriori socket aperti avranno comunque un valore superiore.  Il
-ciclo (\texttt{\small 28--54}) prosegue fintanto che il numero di file
+ciclo (\texttt{\small 26--52}) prosegue fintanto che il numero di file
 descriptor attivi, mantenuto nella variabile \var{n}, è diverso da zero. Se
 pertanto ci sono ancora socket attivi da individuare si comincia con
 descriptor attivi, mantenuto nella variabile \var{n}, è diverso da zero. Se
 pertanto ci sono ancora socket attivi da individuare si comincia con
-l'incrementare (\texttt{\small 30}) l'indice e controllare (\texttt{\small
-  31}) se corrisponde ad un file descriptor in uso analizzando il valore del
+l'incrementare (\texttt{\small 27}) l'indice e controllare (\texttt{\small
+  28}) se corrisponde ad un file descriptor in uso analizzando il valore del
 campo \var{fd} della relativa struttura e chiudendo immediatamente il ciclo
 qualora non lo sia. Se invece il file descriptor è in uso si verifica
 campo \var{fd} della relativa struttura e chiudendo immediatamente il ciclo
 qualora non lo sia. Se invece il file descriptor è in uso si verifica
-(\texttt{\small 31}) se c'è stata attività controllando il campo
-\var{revents}. 
+(\texttt{\small 29}) se c'è stata attività controllando il campo
+\var{revents}.
 
 Di nuovo se non si verifica la presenza di attività il ciclo si chiude subito,
 
 Di nuovo se non si verifica la presenza di attività il ciclo si chiude subito,
-altrimenti si provvederà (\texttt{\small 32}) a decrementare il numero \var{n}
-di file descriptor attivi da controllare e ad eseguire (\texttt{\small 33}) la
-lettura, ed in caso di errore (\texttt{\small 34--37}) al solito lo si
+altrimenti si provvederà (\texttt{\small 30}) a decrementare il numero \var{n}
+di file descriptor attivi da controllare e ad eseguire (\texttt{\small 31}) la
+lettura, ed in caso di errore (\texttt{\small 32--35}) al solito lo si
 notificherà uscendo immediatamente. Qualora invece si ottenga una condizione
 notificherà uscendo immediatamente. Qualora invece si ottenga una condizione
-di \textit{end-of-file} (\texttt{\small 38--47}) si provvederà a chiudere
-(\texttt{\small 39}) anche il nostro capo del socket e a marcarlo
-(\texttt{\small 40}) nella struttura ad esso associata come inutilizzato.
-Infine dovrà essere ricalcolato (\texttt{\small 41--45}) un eventuale nuovo
-valore di \var{max\_fd}. L'ultimo passo è (\texttt{\small 46}) chiudere il
+di \textit{end-of-file} (\texttt{\small 36--45}) si provvederà a chiudere
+(\texttt{\small 37}) anche il nostro capo del socket e a marcarlo
+(\texttt{\small 38}) come inutilizzato nella struttura ad esso associata.
+Infine dovrà essere ricalcolato (\texttt{\small 39--43}) un eventuale nuovo
+valore di \var{max\_fd}. L'ultimo passo è chiudere (\texttt{\small 44}) il
 ciclo in quanto in questo caso non c'è più niente da riscrivere all'indietro
 sul socket.
 
 ciclo in quanto in questo caso non c'è più niente da riscrivere all'indietro
 sul socket.
 
-Se invece si sono letti dei dati si provvede (\texttt{\small 48}) ad
+Se invece si sono letti dei dati si provvede (\texttt{\small 46}) ad
 effettuarne la riscrittura all'indietro, con il solito controllo ed eventuale
 effettuarne la riscrittura all'indietro, con il solito controllo ed eventuale
-uscita e notifica in caso di errore (\texttt{\small 49--52}).
+uscita e notifica in caso di errore (\texttt{\small 47--51}).
 
 Come si può notare la logica del programma è identica a quella vista in
 fig.~\ref{fig:TCP_SelectEchod} per l'analogo server basato su \func{select};
 
 Come si può notare la logica del programma è identica a quella vista in
 fig.~\ref{fig:TCP_SelectEchod} per l'analogo server basato su \func{select};
@@ -3719,10 +3720,10 @@ dai dati in ingresso. Si applicano comunque anche a questo server le
 considerazioni finali di sez.~\ref{sec:TCP_serv_select}.
 
 
 considerazioni finali di sez.~\ref{sec:TCP_serv_select}.
 
 
-\subsection{\textit{I/O multiplexing} con \textit{epoll}}
-\label{sec:TCP_serv_epoll}
+%\subsection{\textit{I/O multiplexing} con \textit{epoll}}
+%\label{sec:TCP_serv_epoll}
 
 
-Da fare.
+%Da fare.
 
 % TODO fare esempio con epoll
 
 
 % TODO fare esempio con epoll