+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}{}
+int main(int argc, char *argv[], char *envp[])
+{
+ ...
+ /* create two pipes to handle process communication */
+ if ( (retval = pipe(pipein)) ) {
+ WriteMess("input pipe creation error");
+ exit(0);
+ }
+ if ( (retval = pipe(pipeout)) ) {
+ WriteMess("output pipe creation error");
+ exit(0);
+ }
+ /* First fork: use child to run barcode program */
+ if ( (pid = fork()) == -1) { /* on error exit */
+ WriteMess("child creation error");
+ exit(0);
+ }
+ /* if child */
+ if (pid == 0) {
+ close(pipein[1]); /* close pipe write end */
+ dup2(pipein[0], STDIN_FILENO); /* remap stdin to pipe read end */
+ close(pipeout[0]);
+ dup2(pipeout[1], STDOUT_FILENO); /* remap stdout in pipe output */
+ execlp("barcode", "barcode", size, NULL); //"-o", "-", NULL);
+ }
+ close(pipein[0]); /* close input side of input pipe */
+ write(pipein[1], argv[1], strlen(argv[1])); /* write parameter to pipe */
+ close(pipein[1]); /* closing write end */
+ waitpid(pid, NULL, 0); /* wait child completion */
+ /* Second fork: use child to run ghostscript */
+ if ( (pid = fork()) == -1) { /* on error exit */
+ WriteMess("child creation error");
+ exit(0);
+ }
+ /* second child, convert PS to JPEG */
+ if (pid == 0) {
+ close(pipeout[1]); /* close write end */
+ dup2(pipeout[0], STDIN_FILENO); /* remap read end to stdin */
+ /* send mime type */
+ write(STDOUT_FILENO, content, strlen(content));
+ execlp("gs", "gs", "-q", "-sDEVICE=jpeg", "-sOutputFile=-", "-", NULL);
+ }
+ /* still parent */
+ close(pipeout[1]);
+ waitpid(pid, NULL, 0);
+ exit(0);
+}
+ \end{lstlisting}
+ \end{minipage}
+ \normalsize
+ \caption{Codice del \textit{CGI} \cmd{BarCodePage}.}
+ \label{fig:ipc_barcode_code}
+\end{figure}
+
+La prima operazione del programma (\texttt{\small 4--12}) è quella di creare
+le due pipe che serviranno per la comunicazione fra i due comandi utilizzati
+per produrre il codice a barre; si ha cura di controllare la riuscita della
+chiamata, inviando in caso di errore un messaggio invece dell'immagine
+richiesta.\footnote{la funzione \func{WriteMess}, non è riportata in
+ \secref{fig:ipc_barcode_code}; essa si incarica semplicemente di formattare
+ l'uscita alla maniera dei CGI, aggiungendo l'opportuno \textit{mime type}, e
+ formattando il messaggio in HTML, in modo che quest'ultimo possa essere
+ visualizzato correttamente da un browser.}
+
+Una volta create le pipe, il programma può creare (\texttt{\small 13-17}) il
+primo processo figlio, che si incaricherà (\texttt{\small 19--25}) di eseguire
+\cmd{barcode}. Quest'ultimo legge dallo standard input una stringa di
+caratteri, la converte nell'immagine postscript del codice a barre ad essa
+corrispondente, e poi scrive il risultato direttamente sullo standard output.
+
+Per poter utilizzare queste caratteristiche prima di eseguire \cmd{barcode} si
+chiude (\texttt{\small 20}) il capo aperto in scrittura della prima pipe, e se
+ne collega (\texttt{\small 21}) il capo in lettura allo standard input, usando
+\func{dup2}. Dato che \cmd{barcode} scrive l'immagine postscript del codice a
+barre sullo standard output, per poter effettuare una ulteriore redirezione il
+capo in lettura della seconda pipe viene chiuso (\texttt{\small 22}) mentre il
+capo in scrittura viene collegato allo standard output (\texttt{\small 23}).
+
+In questo modo all'esecuzione (\texttt{\small 25}) di \cmd{barcode} (cui si
+passa in \var{size} la dimensione della pagina per l'immagine) quest'ultimo
+leggerà dalla prima pipe la stringa da codificare che gli sarà inviata dal
+padre, e scriverà l'immagine postscript del codice a barre sulla seconda.
+
+Al contempo una volta lanciato il primo figlio, il processo padre prima chiude
+(\texttt{\small 26}) il capo inutilizzato della prima pipe (quello in input) e
+poi scrive (\texttt{\small 27}) la stringa da convertire sul capo in output,
+così che \cmd{barcode} possa riceverla dallo standard input. A questo punto
+l'uso della prima pipe è finito ed essa può essere definitivamente chiusa
+(\texttt{\small 28}), si attende poi (\texttt{\small 29}) che l'esecuzione di
+\cmd{barcode} sia completata.
+
+Alla conclusione della sua esecuzione \cmd{barcode} avrà inviato l'immagine
+postscript del codice a barre sul capo in scrittura della seconda pipe; a
+questo punto si può eseguire la seconda conversione, da PS a JPEG, usando il
+programma \cmd{gs}. Per questo si crea (\texttt{\small 30--34}) un secondo
+processo figlio, che poi (\texttt{\small 35--42}) eseguirà questo programma
+leggendo l'immagine postscript creata da \cmd{barcode} dallo standard input,
+per convertirla in JPEG.
+
+Per fare tutto ciò anzitutto si chiude (\texttt{\small 37}) il capo in
+scrittura della seconda pipe, e se ne collega (\texttt{\small 38}) il capo in
+lettura allo standard input. Per poter formattare l'output del programma in
+maniera utilizzabile da un browser, si provvede anche \texttt{\small 40}) alla
+scrittura dell'apposita stringa di identificazione del mime-type in testa allo
+standard output. A questo punto si può invocare \texttt{\small 41}) \cmd{gs},
+provvedendo gli appositi switch che consentono di leggere il file da
+convertire dallo standard input e di inviare la conversione sullo standard
+output.
+
+Per completare le operazioni il processo padre chiude \texttt{\small 44}) il
+capo in scrittura della seconda pipe, e attende la conclusione del figlio
+\texttt{\small 45}); a questo punto può \texttt{\small 46}). Si tenga conto
+che l'operazione di chiudere il capo in scrittura della seconda pipe è
+necessaria, infatti se non venisse chiusa \cmd{gs}, che legge il suo stardard
+input da detta pipe, resterebbe bloccato in attesa di ulteriori dati in
+ingresso (l'unico modo che un programma ha per sapere che l'input è terminato
+è rilevare che lo standard input è stato chiuso), e la \func{wait} non
+ritornerebbe.
+
+
+\subsection{Le funzioni \func{popen} e \func{pclose}}
+\label{sec:ipc_popen}
+
+Come si è visto la modalità più comune di utilizzo di una pipe è quella di
+utilizzarla per fare da tramite fra output ed input di due programmi invocati
+in sequenza; per questo motivo lo standard POSIX.2 ha introdotto due funzioni
+che permettono di sintetizzare queste operazioni. La prima di esse si chiama
+\func{popen} ed il suo prototipo è:
+\begin{prototype}{stdio.h}
+{FILE *popen(const char *command, const char *type)}
+
+Esegue il programma \param{command}, di cui, a seconda di \param{type},
+restituisce, lo standard input o lo standard output nella pipe collegata allo
+stream restituito come valore di ritorno.
+
+\bodydesc{La funzione restituisce l'indirizzo dello stream associato alla pipe
+ in caso di successo e \macro{NULL} per un errore, nel qual caso \var{errno}
+ potrà assumere i valori relativi alle sottostanti invocazioni di \func{pipe}
+ e \func{fork} o \macro{EINVAL} se \param{type} non è valido.}
+\end{prototype}
+
+La funzione crea una pipe, esegue una \func{fork}, ed invoca il programma
+\param{command} attraverso la shell (in sostanza esegue \file{/bin/sh} con il
+flag \code{-c}); l'argomento \param{type} deve essere una delle due stringhe
+\verb|"w"| o \verb|"r"|, per indicare se la pipe sarà collegata allo standard
+input o allo standard output del comando invocato.
+
+La funzione restituisce il puntatore allo stream associato alla pipe creata,
+che sarà aperto in sola lettura (e quindi associato allo standard output del
+programma indicato) in caso si sia indicato \code{"r"}, o in sola scrittura (e
+quindi associato allo standard input) in caso di \code{"w"}.
+
+Lo stream restituito da \func{popen} è identico a tutti gli effetti ai file
+stream visti in \secref{cha:files_std_interface}, anche se è collegato ad una
+pipe e non ad un inode, e viene sempre aperto in modalità
+\textit{fully-buffered} (vedi \secref{sec:file_buffering}); l'unica differenza
+con gli usuali stream è che dovrà essere chiuso dalla seconda delle due nuove
+funzioni, \func{pclose}, il cui prototipo è:
+\begin{prototype}{stdio.h}
+{int pclose(FILE *stream)}
+
+Chiude il file \param{stream}, restituito da una prededente \func{popen}
+attendendo la terminazione del processo ad essa associato.
+
+\bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ errore; nel quel caso il valore di \func{errno} deriva dalle sottostanti
+ chiamate.}
+\end{prototype}
+\noindent che oltre alla chiusura dello stream si incarica anche di attendere
+(tramite \func{wait4}) la conclusione del processo creato dalla precedente
+\func{popen}.
+
+Per illustrare l'uso di queste due funzioni riprenderemo il problema
+precedente; il programma mostrato in \figref{fig:ipc_barcode_code} per quanto
+funzionante, è (volutamente) codificato in maniera piuttosto complesso;
+inoltre nella pratica sconta un problema di \cmd{gs} che non è in
+grado\footnote{nella versione GNU Ghostscript 6.53 (2002-02-13).} di
+riconoscere correttamente l'encapsulated postscript, per cui tutte le volte
+generata una pagina intera, invece che semplice figura delle dimensioni
+corrispondenti al codice a barre.
+
+Se si vuole generare una immagine di dimensioni corrette si deve usare un
+approccio diverso; una possibilità sarebbe quella di ricorrere ad ulteriore
+programma, \cmd{epstopsf}, per convertire in PDF il file EPS generato da
+\cmd{barcode} (utilizzando lo switch \cmd{-E} di quest'ultimo). Utilizzando un
+PDF al posto di un EPS \cmd{gs} esegue la conversione rispettando le
+dimensioni originarie del codice a barre e produce un JPEG delle dimensioni
+adeguate.
+
+Questo però ci porta a scontrarci con una caratteristica peculiare delle pipe,
+che a prima vista non è evidente. Per poter effettuare la conversione di un
+PDF infatti è necessario, per la struttura del formato, dover eseguire delle
+\func{lseek} sul file da convertire; una pipe però è rigidamente sequenziale,
+ed il tentativo di eseguire detta funzioni su un file descriptor associato ad
+una pipe comporta l'immediato fallimento con un errore di \macro{ESPIPE}.
+
+Per questo motivo si è utilizzata una strada diversa, che prevede la
+conversione attraverso \cmd{gs} del PS in un altro formato intermedio, il
+PPM,\footnote{il \textit{Portable PixMap file format} è un formato usato
+ spesso come formato intermedio per effettuare conversioni, è estremamente
+ inefficiente, ma molto facile da manipolare dato che usa caratteri ASCII per
+ memorizzare le immagini.} dal quale poi si può ottenere un'immagine di
+dimensioni corrette attraverso vari programmi di manipolazione (\cmd{pnmcrop},
+\cmd{pnmmargin}) che può essere infine trasformata in PNG.
+
+In questo caso però occorre eseguire sequenza ben quattro comandi diversi,
+inviando l'output di ciascuno all'input del successivo, per poi ottenere il
+risultato finale sullo standard output, il caso più classico dell'uso delle
+pipe.
+
+
+Dato che questo caso ciascun processo deve scrivere il suo output sullo
+standard input del successivo, occorrerà usare \func{popen} aprendo la pipe in
+scrittura.
+
+Il codice del nuovo programma è riportato in \figref{fig:ipc_barcode2_code};
+come si può notare l'ordine di invocazione dei programmi è l'inverso di quello
+in cui ci si aspetta vengano effettivamente eseguiti. Questo non comporta
+nessun problema; infatti la lettura su una pipe è bloccante, per cui ciascun
+processo, per quanto lanciato per primo, si bloccherà in attesa di ricevere
+sullo standard input il risultato dell'elaborazione del precendente, benchè
+quest'ultimo venga invocato dopo.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}{}
+int main(int argc, char *argv[], char *envp[])
+{
+int main(int argc, char *argv[], char *envp[])
+{
+ FILE *pipe[4];
+ FILE *pipein;
+ char *cmd_string[4]={
+ "pnmtopng",
+ "pnmmargin -white 10",
+ "pnmcrop",
+ "gs -sDEVICE=ppmraw -sOutputFile=- -sNOPAUSE -q - -c showpage -c quit"
+ };
+ char content[]="Content-type: image/png\n\n";
+ int i;
+ /* write mime-type to stout */
+ write(STDOUT_FILENO, content, strlen(content));
+ /* execute chain of command */
+ for (i=0; i<4; i++) {
+ pipe[i] = popen(cmd_string[i], "w");
+ dup2(fileno(pipe[i]), STDOUT_FILENO);
+ }
+ /* create barcode (in PS) */
+ pipein = popen("barcode", "w");
+ /* send barcode string to barcode program */
+ write(fileno(pipein), argv[1], strlen(argv[1]));
+ /* close all pipes (in reverse order) */
+ for (i=4; i==0; i--) {
+ pclose((pipe[i]));
+ }
+ exit(0);
+}
+/*
+ * Routine to produce an HTML error message on output
+ */
+void WriteMess(char *mess)
+{
+ printf("Content-type: text/html\n\n");
+ perror(mess);
+ printf("<br>\n");
+}
+}
+
+ \end{lstlisting}
+ \end{minipage}
+ \normalsize
+ \caption{Codice del \textit{cgi-bin} \cmd{BarCode2}.}
+ \label{fig:ipc_barcode2_code}
+\end{figure}
+
+Nel nostro caso il primo passo (\texttt{\small 12}) è scrivere il mime-type
+sullo standard output; a questo punto il processo padre non necessita più di
+eseguire ulteriori operazioni sullo standard output e può tranquillamente
+provvedere alla redirezione. Il primo processo figlio ad essere invocato
+(\texttt{\small 14}) è necessariamente l'ultimo della sequenza, in quanto è
+lui che deve uscire sullo standard output, gli altri saranno tutti rediretti.
+
+Una volta lanciato il processo finale si può iniziare la catena delle
+redirezioni; ogni volta (\texttt{\small 16} e \texttt{\small 20}) duplicheremo
+il file restituito dalla chiamata precedente a \func{popen} sullo standard
+output, in questo modo alla successiva chiamata di \func{popen} il processo
+eseguito scriverà il suo standard output sulla pipe collegata allo standard
+input del precedente.
+
+Alla fine tutto quello che resta da fare è scrivere (\texttt{\small 22}) la
+stringa del codice a barre sulla pipe collegata allo standard input
+dell'ultimo processo lanciato, e poi chiudere tutte le pipe create con
+\func{pclose}.
+