#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define SERVER_PORT 12345	/* wartość wybrana arbitralnie, musi być jednakowa */
                                /* dla klienta i serwera */
#define BUF_SIZE 4096	        /* wielkosć porcji przesyłania danych */
#define QUEUE_SIZE 10

int main(int argc, char *argv[])
{	
  int s, b, l, fd, sa, bytes, on = 1;
  char buf[BUF_SIZE];			/* bufor dla przesyłanych danych */
  struct sockaddr_in channel;		/* przechowuje adres IP */

  /* tworzenie struktury związanej w gniazdem */
  memset(&channel, 0, sizeof(channel));	  /* zerowanie struktury */
  channel.sin_family = AF_INET;
  channel.sin_addr.s_addr = htonl(INADDR_ANY);
  channel.sin_port = htons(SERVER_PORT);

  /* Pasywne otwarcie, oczekiwanie na połączenie */
  s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);   /* utworzenie gniazda */
  if (s < 0) fatal("tworzenie gniazda nie powiodło się");
  setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on));

  b = bind(s, (struct sockaddr *) &channel, sizeof(channel));
  if (b < 0) fatal("nie powiodła się operacja bind");

  l = listen(s, QUEUE_SIZE);		/* maksymalny rozmiar kolejki żądań */
  if (l < 0) fatal("nie powiodła się operacja listen");

  /* Zakończono tworzenie i konfigurowanie gniazda. */
  /* Następuje cukliczne oczekiwanie na ządanie połączenia i jedo przetwarzanie */
  while (1) {
        sa = accept(s, 0, 0);		/* blokada w oczekiwaniu na żądanie połączenia */
        if (sa < 0) fatal("accept failed");

        read(sa, buf, BUF_SIZE);	/* odczyt nazwy pliku z gniazda */

        /* otwarcie pliku i odczyt jego zawartości */
        fd = open(buf, O_RDONLY);	/* otwarcie pliku */
        if (fd < 0) fatal("błąd otwarcia pliku");

        while (1) {
                bytes = read(fd, buf, BUF_SIZE); /* odczyt porcji z pliku */
                if (bytes <= 0) break;		   /* kontrola końca pliku */
                write(sa, buf, bytes);		   /* zapis porcji do gniazda */
        }
        close(fd);				 /* zamknięcie pliku */
        close(sa);				 /* rozłączenie */
  }
}

fatal(char *string)
{
  printf("%s", string);
  exit(1);
}

