// Portions (C) Rudolf Marek
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <strings.h>

#include <signal.h>
#include <sys/wait.h>

#define ECHOPORT	5566
#define	BUFFSIZE	FILENAME_MAX


int do_action(int socket) {
   char   buff[BUFFSIZE];
   int mlen = -1,ptr =0;
	    
               while (mlen)
               {
                 if ( (mlen = recv(socket, buff+ptr,(BUFFSIZE-ptr),0)) == -1)
		 {
	           perror("Chyba pri cteni");
		   return 1;
		 } else 
		 { int limit;
		    limit = ptr + mlen;
	    	    while ((buff[ptr] != 0xA)&&(ptr<limit)) ptr++;
		    if (ptr != limit) mlen = 0;
		 }
		
		}
		buff[ptr]=0;
		fwrite(buff,sizeof(char),ptr,stdout);
//		if ( *((unsigned long *) buff) == 0x20544547) {  
		if (!(memcmp(buff, "GET ", 4)))
		 {  
		FILE *filehndl;
		printf ("\nmam GET\n ");
		    if ((filehndl = fopen(buff+4,"r")) == NULL) {
			perror("Soubor se nepodarilo otevrit");
			return 1;
			}
			
		mlen = -1;
		while (mlen) {
		mlen = fread(buff,sizeof(char),BUFFSIZE,filehndl);
                  if (send(socket, buff, mlen, 0) == -1)
                  {
                     perror("Chyba pri zapisu");
		     fclose(filehndl);
                     return 1;
                  }
		}
		return 0;
		}
		else { 
		printf ("Unknown command\n");
		return 1;
		}
	    return 1;
		
		
    /*

                  if (send(socket, buf, mlen, 0) == -1)
                  {
                     perror("Chyba pri zapisu");
                     break;
                  }

                  printf("%i byte zkopirovano\n", mlen);

                  if ((mlen = recv(c_sockfd, buf, BUFFSIZE, 0)) == -1)
                  {
                     perror("Chyba pri cteni");
                     break;
                  }
               }*/
//            close(socket);
}


void reaper()
{
   union wait status;

   while (wait3(&status, 0, (struct rusage *)0)>0);

   signal(SIGCHLD, reaper);	// re-register (POSIX like) not BSD like
}

int main(int argc, char *argv[])
{
   int    sockfd, c_sockfd;
   struct sockaddr_in my_addr, rem_addr;
   int    rem_addr_length;

   if ((sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
   {
      perror("Socket nelze otevrit");
      exit(1);
   }

   bzero(&my_addr, sizeof(my_addr));
   my_addr.sin_family = AF_INET;
   my_addr.sin_port = htons(ECHOPORT);

   if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr)) == -1)
   {
      perror("Chyba v bind");
      close(sockfd); exit(1);
   }

   if (listen(sockfd, 5) == -1)
   {
      perror("Nelze provest listen");
      close(sockfd); exit(1);
   }

   if (signal(SIGCHLD, reaper)==SIG_ERR)
   {
      perror("Chyba v registraci obsluhy signalu");
      close(sockfd); exit(11);
   }

   while (1)
   {
      rem_addr_length=sizeof(rem_addr);
      if ((c_sockfd = accept(sockfd, (struct sockaddr *)&rem_addr, &rem_addr_length)) == -1)
      {
         if (errno==EINTR) continue;
         perror("Nelze accept");
         close(sockfd); exit(1);
      }

      switch (fork())
      { int exit_code;
         case 0:
	 printf ("Narodilo se dite\n ");

            close(sockfd);
	    exit_code = do_action(c_sockfd);
            close(c_sockfd);
	 printf ("Zemrelo dite\n ");

	    exit(exit_code);

         case -1:
            perror("Chyba pri fork");
            exit(20);

         default:
            close(c_sockfd);
      }
   }
}

