codice:
#include <windows.h>
#include <winsock.h>
#include <stdio.h>
#include <errno.h>
#include <stdint.h>
#include <signal.h>
#include <unistd.h>
#include "errlib.h" // definisce err_msg e generici messaggi di errore
#ifndef uint8_t
#define uint_t8 u_int8_t
#endif
#ifndef uint16_t
#define uint_t16 u_int16_t
#endif
#ifndef uint32_t
#define uint_t32 u_int32_t
#endif
#ifndef socklen_t
#define socklen_t uint32_t
#endif
#define SA struct sockaddr
#define MAX 256
#define MAXSTR 30
#define MAXBUF 255
#define SEPARATORE ";"
#define LISTENQ 15
#define PORTA_DFT 54321
#define UTENTI_DFT 2
#define FILE_DFT "prodotti.txt"
#define SIGCHLD
char *prog;
int num_utenti=0;
void sigchld_h(int signum);
uint32_t find(char *nomefile,char *prodotto, uint8_t Q);
int main(int argc, char **argv){
// inizializzazioni
int listenfd, connfd;
struct sockaddr_in servaddr, cliaddr;
int cliaddrlen;
pid_t pid;
uint8_t zero=0, dcc=255, last, Q;
uint16_t porta=0, prezzo;
uint32_t somma=0, nsomma;
int utenti=0, i, f, flag;
char *nomefile=(char *)malloc(sizeof(char)*MAXBUF);
char *temp1=(char *)malloc(sizeof(char)*MAXBUF);
char *temp2=(char *)malloc(sizeof(char)*MAXBUF);
//char nome_utente[7];
char line[255], ist[10], prodotto[10];
int auth_ret = 0;
int ret=0;
prog = argv[0];
if(argc>4)
{
err_quit("Usage: %s troppi argomenti", prog);
// con troppi parametri esco generando errore
}
//riceve da tastiera -fnomefile -pporta -nfigli
if (argc >1 )
{
for (i=1; i<argc ; i++)
{
if (argv[i][0]=='-') // se l'input e' scritto correttamante con il '-'
{
switch(argv[i][1]) // c'e' la scelta fra
{
case 'f': // nome del file da input
memcpy(nomefile, &argv[i][2], MAXBUF);
break;
case 'p': // numero della porta da tastiera
memcpy(temp1, &argv[i][2], MAXBUF);
porta= atoi(temp1); // converto in intero
break;
case 'n': // numero di figli da tastiera
memcpy(temp2, &argv[i][2], MAXBUF);
utenti=atoi(temp2);
break;
default:
err_quit("Usage: %s parametri non validi; digita -[fpn] parametri", prog);
break;
} // end switch
}// end if argv con il -
else // altriment senza -
{
err_quit("Usage: %s parametri non validi; digita -[fpn] parametrir", prog);
}
} // end for argomenti
} //end if
// se non sono stati inseriti da input imposto i parametri di default
if ((memcpy(nomefile,"",strlen(nomefile)))==0)
{
memcpy(nomefile, FILE_DFT, MAXBUF);
}
if (porta==0)
{
porta= PORTA_DFT;
}
if (utenti== 0)
{
utenti= UTENTI_DFT;
}
//inizializzazioni del socket di ascolto
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(porta);
// funzioni principali: bind collega il socket al servaddr
bind(listenfd, (SA*)&servaddr, sizeof(servaddr));
// la listen si mette in ricezione
listen(listenfd, LISTENQ);
// signal dovrebbe catturare il segnale della morte del figlio
//signal(SIGCHLD, sigchld_h);
while(1){
cliaddrlen = sizeof(cliaddr);
connfd = accept(listenfd,(SA*)&cliaddr,&cliaddrlen);
if (num_utenti==utenti){
send(connfd, "%u\r\n", dcc,MSG_OOB);
close(connfd);
continue;
}
else {
send(connfd,"%u\r\n", zero, MSG_OOB);
num_utenti++;
}
// genera il figlio che eseguira' il lavoro richiesto dal client
if((pid=fork())==0)
{
close(listenfd);
// valori iniziali dei parametri del figlio
somma=0;
f=1;
recv(connfd, line, MAX,MSG_OOB); //legge la linea di comando con l'istruzione
while {strcmp(line,"")!=0) { // confronta la linea con l' insieme vuoto
strncpy(ist,line, 3); // ritaglia le prime tre lettere del messaggio del client
// contenente il comendo da eseguire
switch(ist){
case "USR": // tramite se il comando USR e' ben formato si passa
// dallo stato non autenticato(flag=1)
// allo stato autenticato (flag=0)
byte=strlen(line); //restituisce iil numero di byte
if (byte<10) // la linea ha meno di 10 byte
f=0;
// passa allo stato autenticato con flag a 0 per permettere poi LST, ADD
break;
case "LST":
// cambiare ouput del server
if (f==0) // se sono in stato autenticato (f uguale a 0)
{
// legge dal messaggio prodotto e Quantità
sscanf(line,"ADD%s:%u\r\n",prodotto,&Q);
// apertura file
FILE *fpt= fopen(nomefile,"r");
// legge dal file il record e lo invia al client
while(fscanf(ftp,"%u%s:%u%u",&last, prodotto, &prezzo, &Q)!=EOF)
{
// e lo invia al client tramite connfd (come e' la sintassi??)
// send(connfd,"%u%s:%u%u\r\n", last, prodotto, prezzo, Q);
}
}
break;
case "ADD":
if (f==0)
{
// prende prodotto e Quantita' dalla linea
sscanf(line,"ADD%s:%u\r\n",prodotto, &Q);
// ricerca nel file prodotto, verifica quantita' e ritorna il prezzo, se no da 0
prezzo = find(nomefile, prodotto, Q);
if (prezzo!=0)
send(connfd,"%u\r\n",0); // invia 0 se ha trovato il record, come verifica
else
send(connfd,"%u\r\n",2); // invia 2 se non lo trova
somma = somma + prezzo;
}
break;
case "BYE":
nsomma=hotnl(somma);
if (f==0)
{send(connfd,"%u\r\n", nsomma); }
close(connfd);
break;
default:
send(connfd,"%u\r\n",1);
break;
} // fine dello switch
recv(connfd, line, MAX, MSG_OOB); // legge la prossima istruzione dal client
} // fine del while del menu' di esecuzione delle istruzioni
} //fine dell if con la fork (figlio)
else
{
close(connfd);
}
} // fine del while
exit(0);
} //fine del main
// cerca nel file prodtto e quantita e restituisce il prezzo
// se non lo trova torna 0
uint32_t find(nomefile, prodotto, Q)
{
char prezzoint[3],prezzodec[2], prod[10];
uint32_t prezzo;
FILE *ftp;
int quantita;
int qta =(int)Q;
// apertura file
ftp = fopen(nomefile,"r");
// dal formato
fscanf(ftp,"%s;%s.%s;%d", prod, prezzoint, prezzodec, &quantita);
while(ftp!=EOF){
// confronta il record con le richieste del client
// se lo riconosce
if ((strcmp(prod,prodotto)==0)&&(quantita==qta))
{
strcat(prezzoint, prezzodec);
sscanf(prezzoint,"%d",prezzo);
return prezzo; // leggere il prezzo dal file senza il punto
}
// legge la riga dopo
fscanf(ftp,"%s;%d.%d;%d", prodotto, &prezzoint, &prezzodec, &quantita);
}
return 0;
}
void sigchld_h(int signum){
pid_t pid;
int status;
while((pid=waitpid(-1,&status,WNOHANG))>0)
#ifdef TRACE
err_msg("(%s)info - figlio %d con status %d", prog, pid, status);
#endif
;
num_utenti--;
}