Newsgroup: it.comp.os.linux.development
Titolo: Superserver in C!!!

Salve a tutti!
Devo realizzare per una esercitazione universitaria un "superserver", 
ovvero una specie di demone unix che legge da un file di configurazione 
di servizi locali (es: /bin/cat, /bin/java progJava) associati ad una 
differente porta e in particolare questi servizi possono essere di tipo 
tcp, che udp.
Il servizio richiesto dal cliente è ovviamente selezionato con una 
select, in seguito alla quale viene eseguita una fork dove il figlio 
gestisce l'interazione con il cliente (che praticamente consiste nel 
chiudere i stdin, stdout e stderr, ridirezionarli sulla socket corretta 
ed eseguire una execle del servizio richiesto), mentre il padre ritorna 
alla select.
Ora ho due problemi:
1- dopo che registro tutti i servizi (all'interno di strutture apposite) 
e ne stampo i dati con un loop, non riesco più a printare niente su 
schermo nonostante che la close di stdin stdout sia molto più avanti nel 
codice;
2 - nonostante il precedente errore i servizi di tipo tcp funzionano 
correttamente, mentre quelli udp non danno segni di vita.
Allego il codice del main considerando che vi sono funzioni esterne che 
dovrebbero essere implementate corrrettamente:
int main ( int argc, char *argv[], char** envp )
{	
         //Dichiarazione Variabili
     struct sockaddr_in serv_addr[20],cli_addr;
     int clilen,sockfd,pid,tcp,wait,maxfd,rs,sel,newsockfd,err,i;
     char* lines[MAXSERV];        //creazione di un'array di stringhe 
grande quanto il numero massimo di servizi supportati
     fd_set ready;
     if ( argc!=2 ) //controllo argomenti
     {
         perror ( "Numero argomenti in ingresso errati!!\n" );
         exit(-1);
     }
     FILE* confD=fopen ( argv[1],"r" ); //apertura file (path passata 
come argomento)
     if ( confD==NULL )  //se errore nell'apertura del file
     {
         perror ( "Errore nell'apertura del file \n" );
         exit(-2);
     }
     getNumServ ( confD );     //leggo numero di linee contenute nel 
file passato in ingresso
     if(num_serv>20){
         fprintf(stderr,"Troppi servizi nel file di configurazione, 
numero massimo:%d",MAXSERV);
         exit(-1);
     }
     readConf ( confD,lines );  // lettura del file di configurazione e 
  inserimento dei dati in stringhe
                                         //formattate in maniera standard
     for(i=0;i<num_serv;i++){            //ciclo per ogni riga di testo
         if((err=insertData(i,lines[i]))<0){  //inserimento dei dati 
all'interno del servizio
             fprintf(stderr,"Errore nel formato del file di 
configurazione:%d\n",err);
             exit(-1);
         }
         services[i].pid=-1;              //Inizializzo a -1 i pid dei 
servizi
         createServSock(i);               //Creo un socket per ogni servizio
         bindServSock(i,serv_addr[i]);    //Bindo il socket di ogni 
servizio ad un indirizzo (IP+porta)
         printService(i);                 //stampa dei dati relativi al 
servizio (DEBUG)
     }
     printf("Qui ci arrivo e lo sai!!!");
     signal(SIGCLD,handle_sig);
     for(;;){    //Ciclo infinito
         FD_ZERO(&ready);
             //Controllo quali servizi devono essere settati
         for(i=0;i<num_serv;i++){
             if(strcmp(services[i].mode,"wait")==0 && services[i].pid>0){
             } else {
                 FD_SET(services[i].fd,&ready);
             }
         }
         maxfd=services[num_serv-1].fd+1; //Il massimo fd presente nel 
fd_set è  quello dell'ultimo servizio registrato nell'array
         rs=select(maxfd,&ready,NULL,NULL,NULL);
         if(rs<0){
                 /*Siccome la select ritorna anche alla ricezione di un 
segnale, oltre che alla richiesta di una connessione
             controlliamo se e' stato ricevuto un segnale e nel caso 
ritorniamo ad aspettare una connessione*/
             if(errno==EINTR){
                 continue;   //Torna all'inizio del for per una nuova 
iterazione
             } else{
                 //si e' verificato un errore
                 perror("Errore nella select:");
                 exit(-4);
             }
         }
         if(rs==0){
             fprintf(stderr,"Select==0");
             exit(-4);
         }
         sel=-1;
         for(i=0;i<num_serv;i++){
             if(FD_ISSET(services[i].fd,&ready)){
                 sockfd=services[i].fd;
                 sel=i;
             }
         }
         serv=&services[sel];
         tcp=strcmp(serv->tr,"tcp"); //verifico se il servizio richiesto 
è di tipo tcp
         if(tcp==0){
             clilen=sizeof(cli_addr); 
      //ottengo dimensione indirizzo client
             newsockfd=accept(sockfd,(struct 
sockaddr*)&cli_addr,&clilen);   //accetto la richiesta di connessione 
del client
         }
         pid=fork();                 //Creo un processo figlio
         if(pid<0){                  //Errore nella fork
             perror("Fork error:");
             exit(-5);
         }
         if (pid==0){
                 //Processo Figlio
                 //Chiusura di tutti i socket dei servizi non interessati
             for(i = 0; i < num_serv ; i++ ){
                 if(i!=sel){
                     close(services[i].fd);
                 }
             }
             if(tcp==0){
                 //Chiusura socket server di connessione del servizio 
utilizzato (interessa il padre)
                 close(serv->fd);
                     //Chiusura stdin, stdout, stderr
                 close(0);
                 close(1);
                 close(2);
                     //Redirezione su socket:dup associa al file 
descriptor newsockfd i primi fd disponibili --> in questo caso 0,1 e 2
                 dup(newsockfd);
                 dup(newsockfd);
                 dup(newsockfd);
             } else {
                 //Chiusura stdin, stdout, stderr
                 close(0);
                 close(1);
                 close(2);
                     //Redirezione su socket:dup associa al file 
descriptor newsockfd i primi fd disponibili --> in questo caso 0,1 e 2
                 dup(sockfd);
                 dup(sockfd);
                 dup(sockfd);
             }
                 //Mandiamo in esecuzione il servizio richiesto, 
discriminando a seconda del numero degli argomenti necessari al servizio
             if(serv->numArgs==0){
                 execle(serv->servFullName, serv->servName, NULL, envp);
             } else if (serv->numArgs==1){
                 execle(serv->servFullName, serv->servName,serv->arg1, 
NULL, envp);
             } else if (serv->numArgs==2){
                 execle(serv->servFullName, 
serv->servName,serv->arg1,serv->arg2, NULL, envp);
             } else if (serv->numArgs==3){
                 execle(serv->servFullName, 
serv->servName,serv->arg1,serv->arg2,serv->arg3, NULL, envp);
             } else if (serv->numArgs==4){
                 execle(serv->servFullName, 
serv->servName,serv->arg1,serv->arg2,serv->arg3,serv->arg4, NULL, envp);
             } else if (serv->numArgs==5){
                 execle(serv->servFullName, 
serv->servName,serv->arg1,serv->arg2,serv->arg3,serv->arg4,serv->arg5, 
NULL, envp);
             } else{
                 perror("Invalid number of arguments:");
                 exit(-6);
             }
         } else {
             //Processo Padre
             if(tcp==0){
                 close(newsockfd);               //Chiusura socket 
accettata (Interessa solo al figlio) in modalità TCP
             }
             if(strcmp(serv->mode,"wait")==0){
                 serv->pid=pid;      //scrivo il pid nella struttura del 
servizio lanciato
             }
         }
     } //Fine FOR infinito
     return EXIT_SUCCESS;                //uscita corretta dal superserver
}   //Fine main
Se qualcuno può darmi una mano lo ringrazio infinitamente, dato che il 
professore è una settimana che mi dice che mi guarda il codice ma ancora 
non ho ricevuto risposta e soprattutto dato che devo consegnarla entro 
domenica sera (ma posso ritardare qualche giorno senza problemi).
Grazie,Davide.

 codice;
aggiorno: stampando con fprintf(stderr,"msg"); stampa, con 
fprintf(stdout,"msg") no.
Qualche idea??
Grazie,Davide.

 Grazie,Davide.
Premetto che non ho guardato il codice.
Questo di solito si verifica quando e' nel corpo del figlio che stampi
su stout.
Ricordati che stout e' la shell solo per il padre: dopo il fork il
figlio ha nuovi descrittori.
Quindi, in realta', la fprintf su stdout ha successo solo che non puoi
vederla. Discorso diverso invece per stderr che viene visualizzato sulla
shell attiva (e' importante far vedere gli errori)
Se questo fosse il problema, il mio consiglio e' quello di ridirigere
l'output del/dei figlio/i in un file di log
Spero di essere stato d'aiuto,
Paolo
-- 
A Bright (
http://www.the-brights.net
)
"Anche se detesto quello che dici,
  difendero' fino alla morte il tuo diritto a dirlo."
	(Voltaire)

 
Grazie ho imparato una cosa nuova, ma più che altro rimane il problema 
che via udp non funziona niente.... anche perchè anche stampando alcune 
informazioni con stderr dopo che chiudo stdin,stdout e stderr per poi 
assegnarli alla socket udp non posso più ottenere nulla....

Niente ho risolto.
Il problema stava nel file di configurazione passato in ingresso.... il 
codice è corretto..