ein Kapitel zurück                                           ein Kapitel weiter

Noch eine Programm zu den virtuellen Terminals. Es ist das selbe Programm wie im Kapitel zuvor, nur werden sie aufgefordert ein Passwort einzugeben um die neue virtuelle Konsole zu starten. Die Funktion getpass() ist der reelen Funktion....

char getpass(const char *prompt);  

...nachgebildet. Die 'echte' getpass() - Funktion ist in der Headerdatei <stdlib.h> definiert. Aber diese Funktion ist gut geeignet unser bisher erlerntes zu festigen bzw. neues hinzuzulernen. In diesem Beispiel verwenden wir noch die Funktionen......

int sigemptyset(sigset_t *set);  

...womit wir alle Signale aus der Signalmenge entfernen. Jetzt können wir mit der Funktion....

int sigaddset(sigset_t *set, int signal);  

....einzelne Signale zu der Signalmenge wieder hinzufügen. Das Gegenstück dazu ist übrigens die Funktion.....

int sigdelset(sigset_t *set, int signal);  

...womit wir einzelne Signale aus der Signalmenge löschen könnten (wird aber in unserem Beispiel nicht verwendet). Aktivieren können wir dann die Signalmaske mit.....

int sigprocmask(int wie, sigset_t neu_signale, sigset_t save_alt_signale);  

Wobei wir für wie folgende 3 Konstanten zur Verfügung haben......

  • SIG_BLOCK - Es werden zur aktuellen Signalmaske neu_signale hinzugefügt.
  • SIG_UNBLOCK - Er werden zur aktuellen Sigbalmaske neu_signale entfernt
  • SIG_SETMASK - Neue Signalmasked wird mit den Signalen besetzt die in neu_signale enthalten sind.

Sollten sie z.B. kein Interesse an den alten Signalmasken haben so können sie auch für save_alt_signale den NULL - Zeiger übergeben. Andersrum, wenn sie nur die Signalmaske erfragen wollen können sie bei neu_signale den NULL - Zeiger übergeben.

Eine Signalmaske können sie mit der Funktion....

int sigismember(sigset_t *set, int signal);  

...erfragen. Beispielsweise....

sigset_t signalmaske;

if(sigpending(&signalmaske) == ERROR)
      /*Fehler bei sigpending*/
if(sigismember(&signalmaske, SIGCHLD))
      /*Signal SIGCHLD hängt*/  

Hier fragen wir ab ob das Signal SIGCHLD blockiert wird. Dies fragen wir mit der Funktion......

int sigpending(sigset_t signale);  

...ab. Und anschließend fragen wir mit der Funktion sigismember() die einzelnen Funktionen ab. Dies stellt natürlich nur ein Beispiel da und muss nicht so verwendet werden. Dies nur noch zur Auffrischung der Erinnerung. Mehr dazu finden sie in den Kapiteln der Signale.

Hier nun unser Programm mit den virtuellen Terminals mit Passwortabfrage.........

/*Download:vt2.c*/
#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> #include <signal.h> #include <termios.h> #include <string.h> #include <sys/kd.h> enum{ERROR=-1,OK}; /* Maximale #zeichen für die Eingabe */ #define MAX_PASS_LEN 8 #define PASSWORT "pinguine" /*Zum Abfragen eines Passwortes*/ char *getpass(const char *prompt) {/* +1 für das 0-Byte am Ende zum Terminieren */ static char buf[MAX_PASS_LEN + 1]; char *ptr; sigset_t sig, sigsave; struct termios term, termsave; FILE *fp; int c; if ( (fp = fopen(ctermid(NULL), "r+")) == NULL) return(NULL); setbuf(fp, NULL); //wir schalten die Pufferung aus sigemptyset(&sig); /* Entfernen der Signale aus Signalmenge */ sigaddset(&sig, SIGINT); /*fügen SIGINT dazu */ sigaddset(&sig, SIGTSTP); /*fügen SIGSTP dazu */ /*blockieren von SIGINT und SIGSTP und sichern der Alten Signalmenge in sigsave*/ sigprocmask(SIG_BLOCK, &sig, &sigsave); tcgetattr(fileno(fp), &termsave);/* Sichern des aktuellen Terminals in termsave */ term = termsave; /* copy */ /*Löschen folgender lokalen Flags: ECHO : Ausgabe */ /* ECHOE: Gelöschte Zeichen mit Leerzeichen überschreiben */ /* ECHOK: Zeichen wirklich löschen */ /* ECHONL: Ausgabe von Newline */ term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); /*Wir setzen unsere neuen Attribute*/ tcsetattr(fileno(fp), TCSAFLUSH, &term); /*Gibt "Passwort : " aus*/ fputs(prompt, fp); /*Passwort wird Zeichenweise an die Adresse von ptr geschrieben*/ ptr = buf; while ( (c = getc(fp)) != EOF && c != '\n') { if (ptr < &buf[MAX_PASS_LEN]) *ptr++ = c; } ptr = '\0'; /* null terminate */ putc('\n', fp); /* echo newline */ /* Wir stellen unser altes Terminal wieder her*/ tcsetattr(fileno(fp), TCSAFLUSH, &termsave); /* Wir stellen die alte Signalmaske wieder her */ sigprocmask(SIG_SETMASK, &sigsave, NULL); fclose(fp); return(buf); } 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],*passwort; 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"); /*Wir fragen ein Passwort ab -> "pinguine" */ if(strcmp(passwort=getpass("Passwort : "),PASSWORT)!=0) fehler_exit("Falsches Passwort......\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 ganzen vererbten */ /* Eigenschaften des Elternprozesses*/ close(0); close(1); close(2); close(vterm_fd); /*Jetzt können wir in unserem Kindprozess die Konsole öffen*/ vterm_fd = open(terminal, O_RDWR,0); dup(vterm_fd); dup(vterm_fd); ioctl(vterm_fd, KIOCSOUND, 1000); /*beep an*/ sleep(1); /*1 sekunde beep*/ ioctl(vterm_fd, KIOCSOUND, 0); /*beep aus*/ /*Ausführen von unserer neuen virtuellen Konsole*/ system("setterm -foreground black -background green"); printf("...........................Virtuelle Konsolle" " (tty%d)............................\n\n\n",vterm_nr); system("setterm -foreground white -background black"); execlp("/bin/bash", "bash", NULL); } /*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; }

ein Kapitel zurück          nach oben           ein Kapitel weiter


© 2001,2002 Jürgen Wolf