Addendum 1
Addendum per la lezione dell’18 maggio 2012
1. Possibile base di partenza per la creazione di applicazioni concorrenti in C 2. Makefile per applicazione base
3. Creazione di una pipeline di processi, simulando la ridirezione della shell
4. Modificare il file pipeline.c in modo che ogni processo figlio esegua il comando expr per incrementare il valore ricevuto dal precedente
Addendum 1
Addendum per la lezione dell’18 maggio 2012
1. Possibile base di partenza per la creazione di applicazioni concorrenti in C Soluzione:
/∗ f i l e : b a s e . c
∗ P o s s i b i l e b a s e d i p a r t e n z a p e r a p p l i c a z i o n i c o n c o r r e n t i
∗/
#include <s t d i o . h>
#include < s t d l i b . h>
#include <u n i s t d . h>
#include <s y s / t y p e s . h>
#include <s y s / w a i t . h>
#include <s y s / s t a t . h>
#include < f c n t l . h>
#include <s t d a r g . h>
typedef i n t p i p e t [ 2 ] ; /∗ t i p o p e r p i p e ∗/
#define SCRIT 1
#define LETT 0
i n t Npipe ; /∗ Numero d i p i p e da c r e a r e ∗/
p i p e t ∗ P f d s ; /∗ Array d i p i p e , a l l o c a z i o n e d i n a m i c a ∗/
i n t N f i g l i ; /∗ Numero d i f i g l i da f o r k a r e ∗/
i n t ∗ P i d s ; /∗ Array d i p i d , a l l o c a z i o n e dinamica , SE SERVE ∗/
/∗ a b b i n a m e n t o s n p r i n t f+w r i t e ∗/
void z p r i n t f ( i n t fd , const char ∗ fmt , . . . ) ; /∗ f u n z i o n e f i g l i o DEFINIRE ARGOMENTI ∗/
i n t f i g l i o ( i n t ) ;
/∗ d e f i n i r e i l numero minimo d i a r g o m e n t i ∗/
#define MIN ARG 1
i n t main ( i n t a r g c , char ∗∗ argv , char ∗∗ envp ) { i n t i ; /∗ un i n d i c e ∗/
i n t j ; /∗ a l t r o i n d i c e , s e s e r v e ∗/
/∗ P r o c e s s a m e n t o command l i n e ∗/
i f ( a r g c < MIN ARG+1) {
z p r i n t f ( 2 , ” Uso %s . . . . \ n” , a r g v [ 0 ] ) ; return ( 1 ) ;
}
N f i g l i = 1 ; /∗ DEFINIRE ∗/
Npipe = 1 ; /∗ DEFINIRE ∗/
#i f d e f DEBUG
z p r i n t f ( 1 , ” I n s e r i r e d e n t r o #i f d e f DEBUG i m e s s a g g i d i v e r i f i c a \n” ) ; z p r i n t f ( 1 , ” Per u s a r l i , g c c −DDEBUG −Wall b a s e . c −o b a s e \n” ) ; z p r i n t f ( 1 , ” Per non u s a r l i , g c c −Wall b a s e . c −o b a s e \n” ) ;
#endif
/∗ C r e a z i o n e d e l l e p i p e n e c e s s a r i e ∗/
P f d s = m a l l o c ( Npipe ∗ s i z e o f ( p i p e t ) ) ; i f ( P f d s==NULL) {
z p r i n t f ( 2 , ” I m p o s s i b i l e a l l o c a r e P f d s \n” ) ; return ( 1 ) ;
}
f o r ( i =0; i <Npipe ; i ++) { i f ( p i p e ( P f d s [ i ] ) ! = 0 ) {
z p r i n t f ( 2 , ” I m p o s s i b i l e c r e a r e l a p i p e %d\n” , i ) ; return ( 1 ) ;
} }
/∗ C r e a z i o n e p r o c e s s i f i g l i :
∗ Se i l p a d r e d e v e stampare i v a l o r i d i u s c i t a d e i p r o c e s s i
∗ f i g l i a b b i n a n d o l i a l l ’ i n d i c e , s i devono memorizzare i p i d
∗ i n o r d i n e d i i n d i c e p e r p o i a b b i n a r e i r i s u l t a t i d e l l e w a i t .
∗ L ’ a r r a y d i p i d d e v e e s s e r e a l l o c a t o dinamicamente ∗/
P i d s=m a l l o c ( N f i g l i ∗ s i z e o f ( i n t ) ) ; i f ( P i d s==NULL) {
z p r i n t f ( 2 , ” I m p o s s i b i l e a l l o c a r e P i d s \n” ) ; return ( 1 ) ;
}
f o r ( i =0; i <N f i g l i ; i ++) { P i d s [ i ]= f o r k ( ) ;
switch ( P i d s [ i ] ) {
case 0 : /∗ f i g l i o d i i n d i c e i ∗/
/∗ C h i u s u r a d e l l e p i p e non u s a t e ∗/
return ( f i g l i o ( i ) ) ; /∗ chiamo f u n z i o n e f i g l i o e uso v a l o r e d i r i t o r n o come e x i t d e l p r o c e s s o ∗/
case −1:
z p r i n t f ( 2 , ” I m p o s s i b i l e f o r k a r e i l p r o c e s s o %d\n” , i ) ; return ( 1 ) ;
break ; }
#i f d e f DEBUG
/∗ s o l o i l p r o c e s s o p a d r e e s e g u e q u e s t e l i n e e ∗/
z p r i n t f ( 1 , ” F o r k a t o p r o c e s s o %d p e r i n d i c e %d\n” , P i d s [ i ] , i ) ;
#endif }
/∗ C h i u s u r a d e l l e p i p e non u s a t e ∗/
/∗ Recupero d e l l e i n f o r m a z i o n i d a i p r o c e s s i f i g l i t r a m i t e l a w a i t ,
∗ s e non s e r v e l ’ abbinamento s i d e v e s e m p l i f i c a r e ∗/
f o r ( i =0; i <N f i g l i ; i ++) { i n t p i d x ;
i n t s t a t u s ;
p i d x = w a i t (& s t a t u s ) ;
/∗ a b b i n a m e n t o d e l l e i n f o r m a z i o n i a l l ’ i n d i c e d e l f i g l i o ∗/
f o r ( j =0; j <N f i g l i ; j ++) { i f ( p i d x==P i d s [ j ] ) {
i f (WIFEXITED( s t a t u s ) ) { z p r i n t f ( 1 ,
” I l f i g l i o con i n d i c e %d r i t o r n a %d\n” , j ,
WEXITSTATUS( s t a t u s ) ) ; /∗ ( s t a t u s &0xFF00)>>8 ∗/
} e l s e {
z p r i n t f ( 1 ,
” I l f i g l i o con i n d i c e %d e ’ s t a t o t e r m i n a t o d a l s e g n a l e %d\n” , j ,
WTERMSIG( s t a t u s ) ) ; }
} } }
return ( 0 ) ; }
/∗ F u n zi o n e f i g l i o ∗/
i n t f i g l i o ( i n t i n d i c e ) { i n t r e t v a l ;
/∗ Da f a r e ∗/
r e t v a l = i n d i c e ; /∗ Da f a r e ∗/
return ( r e t v a l ) ; }
void z p r i n t f ( i n t fd , const char ∗ fmt , . . . ) { /∗ p r i n t f wrapper u s i n g w r i t e i n s t e a d ∗/
s t a t i c char msg [ 2 5 6 ] ; v a l i s t ap ;
i n t n ;
v a s t a r t ( ap , fmt ) ;
n=v s n p r i n t f ( msg , 2 5 6 , fmt , ap ) ; w r i t e ( fd , msg , n ) ;
v a e n d ( ap ) ; }
2. Makefile per applicazione base Soluzione:
a l l : b a s e b a s e d b a s e : b a s e . c
g c c −Wall b a s e . c −o b a s e b a s e d : b a s e . c
g c c −Wall −DDEBUG b a s e . c −o b a s e c l e a n :
rm −f b a s e d b a s e
3. Creazione di una pipeline di processi, simulando la ridirezione della shell Soluzione:
/∗ f i l e : p i p e l i n e . c
∗ Esempio d i p i p e l i n e
∗ N p r o c e s s i , o g n i p r o c e s s o l e g g e d a l p r e c e d e n t e e s c r i v e s u l s u c c e s s i v o
∗ a g g i u n g e n d o i l p r o p r i o i n d i c e con una normale p r i n t f ( )
∗/
#include <s t d i o . h>
#include < s t d l i b . h>
#include <u n i s t d . h>
#include <s y s / t y p e s . h>
#include <s y s / w a i t . h>
#include <s y s / s t a t . h>
#include < f c n t l . h>
#include <s t d a r g . h>
typedef i n t p i p e t [ 2 ] ; /∗ t i p o p e r p i p e ∗/
#define SCRIT 1
#define LETT 0
i n t Npipe ; /∗ Numero d i p i p e da c r e a r e ∗/
p i p e t ∗ P f d s ; /∗ Array d i p i p e , a l l o c a z i o n e d i n a m i c a ∗/
i n t N f i g l i ; /∗ Numero d i f i g l i da f o r k a r e ∗/
/∗ a b b i n a m e n t o s n p r i n t f+w r i t e ∗/
void z p r i n t f ( i n t fd , const char ∗ fmt , . . . ) ; /∗ f u n z i o n e f i g l i o DEFINIRE ARGOMENTI ∗/
i n t f i g l i o ( i n t ) ;
/∗ d e f i n i r e i l numero minimo d i a r g o m e n t i ∗/
#define MIN ARG 1
i n t main ( i n t a r g c , char ∗∗ argv , char ∗∗ envp ) { i n t i ; /∗ un i n d i c e ∗/
i n t j ; /∗ a l t r o i n d i c e , s e s e r v e ∗/
/∗ P r o c e s s a m e n t o command l i n e ∗/
i f ( a r g c < MIN ARG+1) {
z p r i n t f ( 2 , ” Uso %s N\n” , a r g v [ 0 ] ) ; return ( 1 ) ;
}
N f i g l i = a t o i ( a r g v [ 1 ] ) ; i f ( N f i g l i <1) {
z p r i n t f ( 2 , ”N>0\n” ) ; return ( 1 ) ;
}
Npipe = N f i g l i − 1 ;
/∗ Ogni f i g l i o i ad e c c e z i o n e d e l l ’ u l t i m o
∗ s c r i v e s u l l a p i p e con i n d i c e i
∗ Ogni f i g l i o ad e c c e z i o n e d e l primo
∗ l e g g e d a l l a p i p e con i n d i c e i −1 ∗/
#i f d e f DEBUG
z p r i n t f ( 1 , ” Esempio d i p i p e l i n e : F0” ) ; f o r ( i =1; i <N f i g l i ; i ++) {
z p r i n t f ( 1 , ” | F%d” , i ) ; }
z p r i n t f ( 1 , ” \n” ) ;
#endif
/∗ C r e a z i o n e d e l l e p i p e n e c e s s a r i e ∗/
P f d s = m a l l o c ( Npipe ∗ s i z e o f ( p i p e t ) ) ; i f ( P f d s==NULL) {
z p r i n t f ( 2 , ” I m p o s s i b i l e a l l o c a r e P f d s \n” ) ;
return ( 1 ) ; }
f o r ( i =0; i <Npipe ; i ++) { i f ( p i p e ( P f d s [ i ] ) ! = 0 ) {
z p r i n t f ( 2 , ” I m p o s s i b i l e c r e a r e l a p i p e %d\n” , i ) ; return ( 1 ) ;
} }
/∗ C r e a z i o n e p r o c e s s i f i g l i :
∗ Non s e r v e Pids , s e m p l i f i c h i a m o ! ∗/
f o r ( i =0; i <N f i g l i ; i ++) { switch ( f o r k ( ) ) {
case 0 : /∗ f i g l i o d i i n d i c e i ∗/
/∗ C h i u s u r a d e l l e p i p e non u s a t e ∗/
f o r ( j =0; j <Npipe ; j ++) {
#i f d e f DEBUG
z p r i n t f ( 1 , ” F i g l i o %d esamina p i p e %d\n” , i , j ) ;
#endif
i f ( ( i ! = 0 ) && ( j != i −1)) { c l o s e ( P f d s [ j ] [ LETT ] ) ;
#i f d e f DEBUG
z p r i n t f ( 1 , ” F i g l i o %d c h i u d e l e t t %d\n” , i , j ) ;
#endif
}
i f ( j != i ) {
c l o s e ( P f d s [ j ] [ SCRIT ] ) ;
#i f d e f DEBUG
z p r i n t f ( 1 , ” F i g l i o %d c h i u d e s c r i t %d\n” , i , j ) ;
#endif
} }
/∗ o p e r o l a r i d i r e z i o n e ! ∗/
i f ( i ! = 0 ) {
/∗ i n i n p u t , p e r t u t t i t r a n n e F0 ∗/
c l o s e ( 0 ) ;
dup ( P f d s [ i − 1 ] [LETT ] ) ; }
i f ( i != N f i g l i −1) {
/∗ i n o u t p u t , p e r t u t t i t r a n n e FN−1 ∗/
c l o s e ( 1 ) ;
dup ( P f d s [ i ] [ SCRIT ] ) ; }
return ( f i g l i o ( i ) ) ; /∗ chiamo f u n z i o n e f i g l i o e uso v a l o r e d i r i t o r n o come e x i t d e l p r o c e s s o ∗/
case −1:
z p r i n t f ( 2 , ” I m p o s s i b i l e f o r k a r e i l p r o c e s s o %d\n” , i ) ; return ( 1 ) ;
break ; }
#i f d e f DEBUG
/∗ s o l o i l p r o c e s s o p a d r e e s e g u e q u e s t e l i n e e ∗/
z p r i n t f ( 1 , ” F o r k a t o p r o c e s s o p e r i n d i c e %d\n” , i ) ;
#endif }
/∗ C h i u s u r a d e l l e p i p e non u s a t e ∗/
f o r ( j =0; j <Npipe ; j ++) {
#i f d e f DEBUG
z p r i n t f ( 1 , ” Padre esamina p i p e %d\n” , j ) ;
#endif
c l o s e ( P f d s [ j ] [ LETT ] ) ; c l o s e ( P f d s [ j ] [ SCRIT ] ) ;
#i f d e f DEBUG
z p r i n t f ( 1 , ” Padre c h i u d e l e t t %d\n” , j ) ; z p r i n t f ( 1 , ” Padre c h i u d e s c r i t %d\n” , j ) ;
#endif }
/∗ Recupero d e l l e i n f o r m a z i o n i d a i p r o c e s s i f i g l i t r a m i t e l a w a i t ,
∗ s e non s e r v e l ’ abbinamento s i d e v e s e m p l i f i c a r e ∗/
f o r ( i =0; i <N f i g l i ; i ++) { i n t s t a t u s ;
i n t p i d x ;
p i d x = w a i t (& s t a t u s ) ; i f (WIFEXITED( s t a t u s ) ) {
z p r i n t f ( 1 ,
” I l f i g l i o con p i d %d r i t o r n a %d\n” , p i d x ,WEXITSTATUS( s t a t u s ) ) ;
} e l s e {
z p r i n t f ( 1 ,
” I l f i g l i o con p i d %d e ’ s t a t o t e r m i n a t o d a l s e g n a l e %d\n” , p i d x ,WTERMSIG( s t a t u s ) ) ;
} }
return ( 0 ) ; }
/∗ F u n zi o n e f i g l i o ∗/
i n t f i g l i o ( i n t i n d i c e ) { i n t r e t v a l ;
char ch ; i n t n r r d ;
/∗ l e g g i a m o t u t t o s t d i n ∗/
f o r ( ; i n d i c e ! = 0 ; ) {
n r r d = r e a d (0 ,& ch , 1 ) ; i f ( n r r d ==1) {
w r i t e (1 ,& ch , 1 ) ; } e l s e {
break ; /∗ s t d i n f i n i t o ∗/
} }
/∗ appendiamo un m e s s a g g i o con una normale p r i n t f ∗/
p r i n t f ( ” Ciao da %d\n” , i n d i c e ) ;
/∗ . . . e s e v o l e s s i m o i n v e c e e s e g u i r e un normale comando
∗ da s h e l l , ad esempio ” l s ” , come potremmo f a r e ? ∗/
r e t v a l = i n d i c e ; /∗ Da f a r e ∗/
return ( r e t v a l ) ; }
void z p r i n t f ( i n t fd , const char ∗ fmt , . . . ) { /∗ p r i n t f wrapper u s i n g w r i t e i n s t e a d ∗/
s t a t i c char msg [ 2 5 6 ] ; v a l i s t ap ;
i n t n ;
v a s t a r t ( ap , fmt ) ;
n=v s n p r i n t f ( msg , 2 5 6 , fmt , ap ) ; w r i t e ( fd , msg , n ) ;
v a e n d ( ap ) ; }
4. Modificare il file pipeline.c in modo che ogni processo figlio esegua il comando expr per incrementare il valore ricevuto dal precedente
Soluzione:
/∗ f i l e : p i p e l i n e . c
∗ Esempio d i p i p e l i n e con e x e c
∗ N p r o c e s s i , o g n i p r o c e s s o l e g g e d a l p r e c e d e n t e e i n c r e m e n t a i l numero
∗ r i c e v u t o d a l p r e c e d e n t e e s e g u e n t o i l comando e x p r .
∗/
#include <s t d i o . h>
#include < s t d l i b . h>
#include <u n i s t d . h>
#include <s y s / t y p e s . h>
#include <s y s / w a i t . h>
#include <s y s / s t a t . h>
#include < f c n t l . h>
#include <s t d a r g . h>
typedef i n t p i p e t [ 2 ] ; /∗ t i p o p e r p i p e ∗/
#define SCRIT 1
#define LETT 0
i n t Npipe ; /∗ Numero d i p i p e da c r e a r e ∗/
p i p e t ∗ P f d s ; /∗ Array d i p i p e , a l l o c a z i o n e d i n a m i c a ∗/
i n t N f i g l i ; /∗ Numero d i f i g l i da f o r k a r e ∗/
/∗ a b b i n a m e n t o s n p r i n t f+w r i t e ∗/
void z p r i n t f ( i n t fd , const char ∗ fmt , . . . ) ; /∗ f u n z i o n e f i g l i o DEFINIRE ARGOMENTI ∗/
i n t f i g l i o ( i n t ) ;
/∗ d e f i n i r e i l numero minimo d i a r g o m e n t i ∗/
#define MIN ARG 1
i n t main ( i n t a r g c , char ∗∗ argv , char ∗∗ envp ) { i n t i ; /∗ un i n d i c e ∗/
i n t j ; /∗ a l t r o i n d i c e , s e s e r v e ∗/
/∗ P r o c e s s a m e n t o command l i n e ∗/
i f ( a r g c < MIN ARG+1) {
z p r i n t f ( 2 , ” Uso %s N\n” , a r g v [ 0 ] ) ;
return ( 1 ) ; }
N f i g l i = a t o i ( a r g v [ 1 ] ) ; i f ( N f i g l i <1) {
z p r i n t f ( 2 , ”N>0\n” ) ; return ( 1 ) ;
}
Npipe = N f i g l i − 1 ;
/∗ Ogni f i g l i o i ad e c c e z i o n e d e l l ’ u l t i m o
∗ s c r i v e s u l l a p i p e con i n d i c e i
∗ Ogni f i g l i o ad e c c e z i o n e d e l primo
∗ l e g g e d a l l a p i p e con i n d i c e i −1 ∗/
#i f d e f DEBUG
z p r i n t f ( 1 , ” Esempio d i p i p e l i n e : F0” ) ; f o r ( i =1; i <N f i g l i ; i ++) {
z p r i n t f ( 1 , ” | F%d” , i ) ; }
z p r i n t f ( 1 , ” \n” ) ;
#endif
/∗ C r e a z i o n e d e l l e p i p e n e c e s s a r i e ∗/
P f d s = m a l l o c ( Npipe ∗ s i z e o f ( p i p e t ) ) ; i f ( P f d s==NULL) {
z p r i n t f ( 2 , ” I m p o s s i b i l e a l l o c a r e P f d s \n” ) ; return ( 1 ) ;
}
f o r ( i =0; i <Npipe ; i ++) { i f ( p i p e ( P f d s [ i ] ) ! = 0 ) {
z p r i n t f ( 2 , ” I m p o s s i b i l e c r e a r e l a p i p e %d\n” , i ) ; return ( 1 ) ;
} }
/∗ C r e a z i o n e p r o c e s s i f i g l i :
∗ Non s e r v e Pids , s e m p l i f i c h i a m o ! ∗/
f o r ( i =0; i <N f i g l i ; i ++) { switch ( f o r k ( ) ) {
case 0 : /∗ f i g l i o d i i n d i c e i ∗/
/∗ C h i u s u r a d e l l e p i p e non u s a t e ∗/
f o r ( j =0; j <Npipe ; j ++) {
#i f d e f DEBUG
z p r i n t f ( 1 , ” F i g l i o %d esamina p i p e %d\n” , i , j ) ;
#endif
i f ( ( i ! = 0 ) && ( j != i −1)) { c l o s e ( P f d s [ j ] [ LETT ] ) ;
#i f d e f DEBUG
z p r i n t f ( 1 , ” F i g l i o %d c h i u d e l e t t %d\n” , i , j ) ;
#endif
}
i f ( j != i ) {
c l o s e ( P f d s [ j ] [ SCRIT ] ) ;
#i f d e f DEBUG
z p r i n t f ( 1 , ” F i g l i o %d c h i u d e s c r i t %d\n” , i , j ) ;
#endif
} }
/∗ o p e r o l a r i d i r e z i o n e ! ∗/
i f ( i ! = 0 ) {
/∗ i n i n p u t , p e r t u t t i t r a n n e F0 ∗/
c l o s e ( 0 ) ;
dup ( P f d s [ i − 1 ] [LETT ] ) ; }
i f ( i != N f i g l i −1) {
/∗ i n o u t p u t , p e r t u t t i t r a n n e FN−1 ∗/
c l o s e ( 1 ) ;
dup ( P f d s [ i ] [ SCRIT ] ) ; }
return ( f i g l i o ( i ) ) ; /∗ chiamo f u n z i o n e f i g l i o e uso v a l o r e d i r i t o r n o come e x i t d e l p r o c e s s o ∗/
case −1:
z p r i n t f ( 2 , ” I m p o s s i b i l e f o r k a r e i l p r o c e s s o %d\n” , i ) ; return ( 1 ) ;
break ; }
#i f d e f DEBUG
/∗ s o l o i l p r o c e s s o p a d r e e s e g u e q u e s t e l i n e e ∗/
z p r i n t f ( 1 , ” F o r k a t o p r o c e s s o p e r i n d i c e %d\n” , i ) ;
#endif }
/∗ C h i u s u r a d e l l e p i p e non u s a t e ∗/
f o r ( j =0; j <Npipe ; j ++) {
#i f d e f DEBUG
z p r i n t f ( 1 , ” Padre esamina p i p e %d\n” , j ) ;
#endif
c l o s e ( P f d s [ j ] [ LETT ] ) ; c l o s e ( P f d s [ j ] [ SCRIT ] ) ;
#i f d e f DEBUG
z p r i n t f ( 1 , ” Padre c h i u d e l e t t %d\n” , j ) ; z p r i n t f ( 1 , ” Padre c h i u d e s c r i t %d\n” , j ) ;
#endif }
/∗ Recupero d e l l e i n f o r m a z i o n i d a i p r o c e s s i f i g l i t r a m i t e l a w a i t ,
∗ s e non s e r v e l ’ abbinamento s i d e v e s e m p l i f i c a r e ∗/
f o r ( i =0; i <N f i g l i ; i ++) { i n t s t a t u s ;
i n t p i d x ;
p i d x = w a i t (& s t a t u s ) ; i f (WIFEXITED( s t a t u s ) ) {
z p r i n t f ( 1 ,
” I l f i g l i o con p i d %d r i t o r n a %d\n” , p i d x ,WEXITSTATUS( s t a t u s ) ) ;
} e l s e {
z p r i n t f ( 1 ,
” I l f i g l i o con p i d %d e ’ s t a t o t e r m i n a t o d a l s e g n a l e %d\n” , p i d x ,WTERMSIG( s t a t u s ) ) ;
} }
return ( 0 ) ;
}
/∗ F u n zi o n e f i g l i o ∗/
i n t f i g l i o ( i n t i n d i c e ) { i n t n r r d ;
char mybuff [ 2 5 6 ] ; /∗ d e v e c o n t e n e r e almeno l o s t d o u t d e l p r e c e d e n t e ∗/
/∗ t u t t i i f i g l i r i c e v o n o l o s t d o u t d e l p r e c e d e n t e
∗ ad e c c e z i o n e d e l primo e c o n v e r t o n o l a s t r i n g a
∗ i n numero ∗/
i f ( i n d i c e ==0) { mybuff [ 0 ] = ’ 1 ’ ; mybuff [ 1 ] = ’ \0 ’ ; } e l s e {
n r r d = r e a d ( 0 , mybuff , s i z e o f ( mybuff ) ) ;
#i f d e f DEBUG
z p r i n t f ( 2 , ” F i g l i o %d r i c e v e %d c a r a t t e r i \n” , i n d i c e , n r r d ) ;
#endif
i f ( n r r d <1) {
#i f d e f DEBUG
z p r i n t f ( 2 , ” F i g l i o %d t e r m i n a \n” , i n d i c e ) ;
#endif
return ( − 1 ) ; }
/∗ l ’ o u t p u t g e n e r a t o da e x e c ha un r i t o r n o a capo a l l a f i n e ,
∗ s o s t i t u i a m o l o con ’ \ 0 ’ terminando l a s t r i n g a ∗/
mybuff [ n r r d −1]= ’ \0 ’ ;
#i f d e f DEBUG
z p r i n t f ( 2 , ” F i g l i o %d r i c e v e \”% s \”\ n” , i n d i c e , mybuff ) ;
#endif }
/∗ o r a e s e g u i a m o e x p r ∗/
e x e c l p ( ” e x p r ” , ” e x p r ” , mybuff , ”+” , ” 1 ” ,NULL ) ; }
void z p r i n t f ( i n t fd , const char ∗ fmt , . . . ) { /∗ p r i n t f wrapper u s i n g w r i t e i n s t e a d ∗/
s t a t i c char msg [ 2 5 6 ] ; v a l i s t ap ;
i n t n ;
v a s t a r t ( ap , fmt ) ;
n=v s n p r i n t f ( msg , 2 5 6 , fmt , ap ) ; w r i t e ( fd , msg , n ) ;
v a e n d ( ap ) ; }