#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>


/* Puffergroesse fuer Mailadresse */
#define MAIL_ADDR_LEN       64

/* Puffergroesse fuer Mail-Quelldateiname */
#define MAIL_FILE_NAME_LEN 256

/* Puffergroesse fuer cf / df-Dateiname mit Pfadangabe "spool/" */
#define JOB_FILEPATH_LEN    32


/******************************************************************************
 * get_next_number: Naechste zu vergebene Auftragsnummer ermitteln            *
 ******************************************************************************
 * Rueckgabewert: naechste Auftragsnummer                                     *
 ******************************************************************************/

int get_next_number()
{
  int curr_num;      /* Nummer des momentan betrachteten Auftrags */
  int next_num = 1;  /* Naechste zu vergebende Auftragsnummer */
  int ret;

  DIR           *dir;
  struct dirent *entry;


  /* Spool-Verzeichnis oeffnen */
  dir = opendir("spool");
  if(dir == NULL)
  {
    perror("get_next_number: opendir");
    exit(EXIT_FAILURE);
  }


  /* Spool-Verzeichnis durchlaufen */
  while(1)
  {
    /* readdir liefert als Rueckgabewert NULL, wenn das Verzeichnis aus-
       gelesen wurde ODER ein Fehler aufgetreten ist. Um dies zu unter-
       scheiden wird vor jedem readdir-Aufruf errno auf 0 gesetzt.
       Im Fehlerfall ist der Rueckgabewert NULL und errno != 0. */
    errno = 0;
    entry = readdir(dir);
    if(entry == NULL)
    {
      if(errno != 0)
      {
        /* Fehler bei readdir */
        perror("get_next_number: readdir");
        exit(EXIT_FAILURE);
      }
      else break; /* Verzeichnis ausgelesen, while Schleife verlassen */
    }

    /* Nur cfxxxx-Dateien bei Ermittlung der Auftragsnummer beruecksichtigen */
    if(entry->d_name[0] != 'c') continue; /* Keine c... -Datei */

    if(strlen(entry->d_name) != 6) continue; /* Keine cfxxxx-Datei */


    /* Nummer aus Dateiname ermitteln */
    ret = sscanf(entry->d_name, "cf%d", &curr_num);
    if(ret != 1)
    {
      /* Nummer konnte nicht aus Zeichenkette konvertiert werden */
      printf("Ungueltige Datei \"%s\" im spool-Verzeichnis!\n", entry->d_name);
      printf("Datei wird ignoriert!\n");
    }
    else
    {
      /* Naechster Auftrag bekommt groesste gefundene Nummer + 1 */
      if(curr_num >= next_num) next_num = curr_num + 1;
    }
  }

  closedir(dir);

  return next_num;
}


/******************************************************************************
 * newjob: Auftrag anlegen                                                    *
 ******************************************************************************
 * Eingabe: empfaenger: Empfaengeradresse                                     *
 *          mailinhalt: Eingabekanal mit Mailinhalt                           *
 ******************************************************************************/

void newjob(char *empfaenger, FILE *mailinhalt)
{
   int   c;
   FILE *cf_fileptr;  /* Handle fuer anzulegende cf-Datei */
   FILE *df_fileptr;  /* Handle fuer anzulegende df-Datei */

   int   job_num;     /* Auftragsnummer */

   /* Dateinamen fuer cf- und df-Datei, fortlaufend nummeriert,
      inkl. Pfadangabe "spool/" */
   char  cffile[JOB_FILEPATH_LEN];
   char  dffile[JOB_FILEPATH_LEN];


   /* Naechste Job-Nummer ermitteln */
   job_num = get_next_number();


   /* Mailadresse in Datei spool/cf<job_num> ablegen */

   /* cf-Datei erstellen */
   sprintf(cffile, "spool/cf%04d", job_num);
   cf_fileptr = fopen(cffile, "w");
   if(cf_fileptr == NULL) /* Fehler ? */
   {
      perror("newjob: create cf-file");
      exit(EXIT_FAILURE);
   }

   /* Mailadresse in Datei schreiben */
   fprintf(cf_fileptr, empfaenger);
   fclose(cf_fileptr);


   /* Mailinhalt nach Datei spool/df<job-num> kopieren */

   /* df-Zieldatei anlegen */
   sprintf(dffile, "spool/df%04d", job_num);
   df_fileptr = fopen(dffile, "w");
   if(df_fileptr == NULL) /* Fehler ? */
   {
      perror("newjob: create df-file");
      exit(EXIT_FAILURE);
   }

   /* Mailinhalt kopieren */
   while((c = getc(mailinhalt)) != EOF)
   {
      putc(c, df_fileptr);
   }

   /* df-Zieldatei schliessen */
   fclose(df_fileptr);

   printf("Auftrag Nr. %04d erfolgreich angelegt!\n\n", job_num);
}


/******************************************************************************
 * main: Empfaengeradresse und zu versendende Maildatei ermitteln,            *
 *       anschliessend neuen Auftrag anlegen                                  *
 ******************************************************************************/

int main()
{
   char  empfaenger[MAIL_ADDR_LEN];         /* Eingegebene Mail-Adresse */
   char  mail_filename[MAIL_FILE_NAME_LEN]; /* Eingegebener Name der Mail-Quelldatei */
   FILE *mailinhalt;
   int   ret;


   /* spool Verzeichnis anlegen, alle Permission-Bits setzen,
      prozessweite "umask" veraendert diese Bits */
   ret = mkdir("spool", S_IRWXU | S_IRWXG | S_IRWXO);
   if(ret != 0) /* Fehler, ausgenommen "Verzeichnis existiert schon" ? */
   {
      if(errno != EEXIST)
      {
         perror("bmail: mkdir");
         return EXIT_FAILURE;
      }
   }


  /* Mail-Adresse einlesen */
  printf("Bitte geben Sie die Mail-Adresse ein:\n");
  scanf("%s", empfaenger);


  /* Mail-Quelldateiname einlesen */
  printf("Bitte geben Sie den Namen der Mail-Datei ein:\n");
  scanf("%s", mail_filename);


  /* Zur Kontrolle */
  printf("Sie haben eingegeben:\n%s\n%s\n", empfaenger, mail_filename);


  /* Datei mit Mailinhalt oeffnen */
  mailinhalt = fopen(mail_filename, "r");
  if(mailinhalt == NULL) /* Fehler ? */
  {
    perror("bmail: open mail source file");
    return EXIT_FAILURE;
  }


  /* Neuen Auftrag anlegen */
  newjob(empfaenger, mailinhalt);


  /* Datei mit Mailinhalt schliessen */
  fclose(mailinhalt);

  return EXIT_SUCCESS;
}
