#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/vt.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdarg.h>
#include <fcntl.h>

enum{ERROR=-1,OK};


void fehler_exit(char *error_msg,...)
{
  va_list az;
  va_start(az,error_msg);
  vprintf(error_msg,az);
  va_end(az);
  exit(0);
}


int main()
{
  int vterm_nr, vterm_fd;
  int status;
  struct vt_stat vterm_stat;
  char terminal[100];
  pid_t kindprozess;

/*Zuerst öffnen wir die Gerätedatei /dev/tty da wir für ioctl
  ein Filedeskriptor benötigen */

if((vterm_fd = open("/dev/tty", O_RDWR, 0)) == ERROR)
fehler_exit("Kann /dev/tty nicht öffnen.....\n");

/*Jetzt prüfen wir ob tty eine virtuelle Konsole ist*/
  if(ioctl(vterm_fd, VT_GETSTATE, &vterm_stat) == ERROR)
       fehler_exit("tty ist keine virtuelle Konsole..\n");

/*Jetzt suchen wir uns eine freie virtuelle Konsole*/
  if(ioctl(vterm_fd, VT_OPENQRY, &vterm_nr) == ERROR || vterm_nr == ERROR)
       fehler_exit("Keine freie konsole vorhanden...\n");

  sprintf(terminal,"/dev/tty%d",vterm_nr);
  printf("Versuche neues Terminal %s zu öffnen........\n",terminal);

/*Jetzt wollen wir überprüfen ob wir auf unserem neuen virt. Term Lesen und Schreiben   dürfen*/
  if(access(terminal, (W_OK|R_OK)) == ERROR)
       fehler_exit("Unzureichend Rechte auf das Terminal......\n");


/*Jetzt erzeugen wir einen neuen Prozess für unser neues Terminal*/
  if((kindprozess=fork()) == OK)
    {
/*Wir aktivieren die neuen Konsole warten bis sie wirklich aktiviert wird*/
       ioctl(vterm_fd, VT_ACTIVATE, vterm_nr);
       ioctl(vterm_fd, VT_WAITACTIVE, vterm_nr);

/*Wir richten eine neue Session ein*/
       setsid();

/*Wir schließen stdin,stdout und stderr und vterm_fd da wir ja eine neuen virtuelle
Konsole starten wollen und nicht mit dem ganzprintf("%s\n",terminal);en vererbten Eigenschaften des Elternprozesses*/
       close(0); close(1); close(2); close(vterm_fd);

/*Jetzt können wir in unserem Kindprozess die Kprintf("%s\n",terminal);konsole öffen*/
       vterm_fd = open(terminal, O_RDWR,0);
       printf("%s\n",terminal);
       dup(vterm_fd);  dup(vterm_fd);

/*Ausführen von unserer neuen virtuellen Konsole*/
       printf("...........................Virtuelle Konsolle (tty%d)..................\n\n\n",vterm_nr);
       execlp("/bin/bash", "bash", NULL); printf("%s\n",terminal);
    }    //Ende Kindprozess

  wait(NULL);   //Elternprozess wartet auf den Kindprozess

/*Alte Konsole wieder aktivieren und Speicher der virtuellen Konsole wieder freigeben*/
  ioctl(vterm_fd, VT_ACTIVATE, vterm_stat.v_active);
  ioctl(vterm_fd, VT_WAITACTIVE, vterm_stat.v_active);
  ioctl(vterm_fd, VT_DISALLOCATE, vterm_nr);

  return 0;
}
