/*
 * daytime-server-tcp - a simple TCP server
 */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <arpa/inet.h>

#define DEFAULTPORT 13
#define LINEMAX 1000

int main(int argc, char *argv[])
  {
  int server, client;
  socklen_t len;
  struct sockaddr_in server_addr;
  struct sockaddr_in client_addr;
  time_t t;
  struct tm *tm;
  char timemsg[LINEMAX];
  int portnumber;

  /* Rest der struct nullsetzen */
  memset(&(server_addr.sin_zero), '\0', 8);

  /* Kommandozeile einlesen */
  switch (argc)
    {
    case 1:
      /* Keine Argumente - default port */
      portnumber = DEFAULTPORT; break;
    case 2:
      /* Portnummer von der Kommandozeile */
      portnumber = atol(argv[1]);
      if (portnumber <= 0 || portnumber > 65535)
        {
        perror("Falsche Portnummer (muss zwischen 0 und 65535 liegen)");
        return 1;
        }  
      break;
    default:
      fprintf(stderr, "Usage: %s [portnumber] (0 < port_number < 65535)\nBeispiel: %s 1024\n", argv[0], argv[0]);
      return 1;
    }

  /* Set protocol to "0" to have socket() choose the correct protocol. */
  if ((server = socket(PF_INET, SOCK_STREAM, 0)) < 0)
    {
    perror("Fehler beim Anlegen des Socket");
    return 2;
    }

  /* Server-Adress-Struktur vorbereiten */
  memset( &server_addr, 0, sizeof (server_addr));
  server_addr.sin_family = AF_INET;
  server_addr.sin_port = htons(portnumber);
  server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  /* Listen to an interface with a specific IP (requires <arpa/inet.h>). */
  /* inet_aton("127.0.0.1", &(server_addr.sin_addr)); */

  if (bind(server, (struct sockaddr *)&server_addr, sizeof server_addr) < 0)
    {
    perror("Fehler bei bind (Portnummer < 1024? Dann musst Du root sein)");
    return 3;
    }

  /* Daemonisieren */
  switch (fork())
    {
    case  0: break;
    case -1: perror("Fork fehlgeschlagen"); return 4; break;
    default: close(server); return 0; break;
    }

  listen(server, 5);

  /* warten auf Anfragen */
  for (;;)
    {
    len = sizeof(client_addr);

    if ((client = accept(server, (struct sockaddr *)&client_addr, &len)) < 0)
      {
      perror("Accept fehlgeschlagen");
      return 4;
      }
    fprintf(stderr, "Connect von %s\n",inet_ntoa(client_addr.sin_addr));
    /* Zeit bestimmen */
    t = time(NULL);
    tm = localtime(&t);
    sprintf(timemsg, "%.4i-%.2i-%.2i %.2i:%.2i:%.2i %s\n",
          tm->tm_year + 1900,
          tm->tm_mon + 1,
          tm->tm_mday,
          tm->tm_hour,
          tm->tm_min,
          tm->tm_sec,
          tm->tm_zone);

    /* Uhrzeit zum Client senden */
    if ((send(client, timemsg, strlen(timemsg), 0)) < 0)
      {
      perror("Senden fehlgeschlagen");
      return 6;
      }

    if (close(client) < 0)
      {
      perror("daytimed-tcp close");
      return 7;
      }
    }
  }

