
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>

#define SIZE sizeof(struct sockaddr_in)

#ifdef WORDS_BIGENDIAN
#define swap_short(sh) (sh)
#else
#define swap_short(sh) ((((sh)&0xff00)>>8)|(((sh)&0x00ff)<<8))
#endif

void catcher(int sig);
int newsockfd;

int main(void)
{
    int sockfd;
    char c;
    struct sockaddr_in server;
    static struct sigaction act;
    
    act.sa_handler = catcher;
    sigfillset(&(act.sa_mask));
    sigaction(SIGPIPE, &act, NULL);
    
    server.sin_family = AF_INET;
    server.sin_port = swap_short(20000);
    server.sin_addr.s_addr = inet_addr("195.205.84.133"); //INADDR_ANY
    
    //ustaw punkt koncowy transportu
    if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
	perror("socked call failed");
	exit (1);
    }
    
    //polacz gniazdo z adresem serwera
    if ( bind(sockfd, (struct sockaddr *)&server, SIZE) == -1)
    {
	perror("connect call failed");
	exit (1);
    }

    if( listen(sockfd, 5) == -1)
    {
	perror("listen call failed");
	exit(1);
    }
    
    for(;;)
    {
	//przyjmij polaczenie
	if( (newsockfd = accept(sockfd, NULL, NULL)) == -1)
	{
	    perror("accept call failed");
	    continue;
	}
	
	//utworz proces potomny do pracy z polaczeniem
	if( fork() == 0)
	{
	    while(recv(newsockfd, &c, 1, 0) > 0)
	    {
		c = toupper(c);
		send(newsockfd, &c,1, 0);
	    }
	    
	    /* gdy klient nie wysyla dluzej informacji
	    gniazdo moze byc zamkniete i proces
	    potomny zakonczony */
	    
	    close(newsockfd);
	    exit(0);
	}
	
	//rodzic nie potrzebuje newsockfd
	close(newsockfd);
    }
}


void catcher(int sig)
{
    close(newsockfd);
    exit(0);
}
    
