ein Kapitel zurück                                           ein Kapitel weiter

Bevor wir zu Terminal Ein/Ausgabe kommen muss ich Ihnen erst noch erklären was es mit Terminals überhaupt auf sich hat unter Linux.

Terminals sind über serielle Schnittstelle mit Linux-Rechnern verbunden. Um sie nicht zu verwirren, wenn sie eine Konsole verwenden, arbeiten sie in gleicher Weise wie mit einer Terminalleitung, auch wenn kein Verbindung über die serielle Schnittstelle vorliegt. Somit ist die Grundlage eines auf dem Bildschirm konfigurierten Terminals gleichwertig zu der über einem externen angeschlossenen Terminals.

Die Ein/Ausgabe eine Terminals sind in der Grundeinstellung immer Zeilengepuffert. read wird also erst beendet wenn die ENTER - Taste gedrückt wurde. Drücken sie stattdessen STRG+D liefert read 0 (EOF) zurück, dies bedeutet meist die Terminierung des Programms. Diese Verhalten kann mit mit O_NONBLOCK bei open oder nachträglich mit fcntl verändern.

Ein Tipp am Rande: Sie können einige gezeigt Möglichkeiten hier auch verwenden um 2 PC mit einem Nullmodemkabel zu koppeln. Ein Nullmodemkabel können sie an der seriellen Schnittstelle des jeweiligen PC's anhängen. Ein Nullmodemkabel spielt jedem anderen Rechner vor er sei ein Modem.Dies gelingt in dem man die Anschlußbelegung der beiden Kabelenden an der seriellen Schnittstelle ändert. Somit lassen sich bequem Daten von dem einen PC zum anderen senden. Dies funktioniert auch von Linux auf Windows. Nehmen sie für Linux als Terminalprogramm getty und für Windows das HyperTerminal. Entweder sie basteln sich ein Nullmodemkabel selbst zusammen, oder sie kaufen sich eins für etwa 5-10 Euro in jedem guten Elektro-oder-PC-Laden.

Kommen wir zu einem weiterem wichtigem Kapitel in der Linux/Unix-Programmierung. Nämlich der Terminal Ein/Ausgabe. Zugegeben in der Zeit der GUI`s mag dieses Thema altertümlich erscheinen, aber wenn es um Netzwerk-Programmierung geht sind Terminals unschlagbar. Das Kapitel Terminal E/A handelt z.B. von solche Themen:

Wie kann ich ein Zeichen von der Tastatur lesen?
Wie kann man den Standartzeichensatz von Linux verändern?
Wie kann ich herausfinden welche Terminal gerade offen sind?  

Sie haben zwar schon mit Curses schon eine Möglichkeit dazu kennen gelernt, nur scheint Curses für manche Anwendungen zu Umfangreich oder einfach zu Umständlich zu sein.

Bevor wir loslegen muss ich Ihnen noch schnell die zwei Möglichkeiten erklären die uns für die Terminal-Modi zur Verfügung stehen:

  • Zeilenorientierter Modus (canonical mode = Kanonischer Modus). Dieser Modus ist die Voreinstellung von den Terminals und sorgt dafür das nur ganze Zeilen verarbeitet bzw. zurückgeliefert werden.
  • Zeichenorientierter Modus (noncanoncial mode = Nicht Kanonischer Modus). Hier werden einzelne Zeichen abgearbeitet und auch Zeichenweise wieder zurückgeliefert. Dadurch funktionieren einige Steuerzeichen nicht das diese ja aus mehr als 1 Zeichen bestehen.

Jetzt will ich Ihnen zeigen wie es möglich ist einzelne Tasten von einem Programm abzufangen bzw. auszugebende Zeichen zu manipulieren. Alle Attribute die man bei einem Terminal setzen bzw. abfragen kann sind in einer Struktur, die in der Headerdatei <termios.h> definiert sind, enthalten. Hier die Struktur:

struct termios {
                         tcflag_t c_iflag;       /*Eingabe-Flag*/
                         tcflag_t c_oflag;      /*Ausgabe-Flag*/
                         tcflag_t c_cflag;      /*Kontroll-Flag*/
                         tcflag_t c_lflag;       /*Lokale Flags*/
                         cc_t c_cc[NCCS];   /*Steuerzeichen*/
                      };  

Jetzt benötigen wir noch das Wissen welche Werte wir an den einzelnen Strukturvariablen setzen bzw. erfragen können.

Zuerst die Werte des Eingabe-Flag 'tcflag_t c_iflag' (Eingabe-Flags) die möglich sind.........

Konstante Bedeutung
BRKINT  Generieren von SIGINT bei Tastendruck auf BREAK
ICRNL  Umwandeln von CR in NL bei der Eingabe
IGNBRK Break Ignorieren
IGNCR CR Ignorieren
IGNPAR  Bytes mit Paritätsprüfung ignorieren
IMAXBEL  Akustisches Signal wenn Eingabepuffer voll ist BREAK ignorieren
INLCR  Umwandeln von NL in CR bei CR ignorieren der Eingabe
INPCK  Einschalten der Eingabe-Partitätsprüfung
ISTRIP  Abschneiden des 8.Bit bei Eingabezeichen
IUCLC  Umwandeln von Groß in Kleinbuchstaben
IXANY  Wartet auf ein X-beliebiges Zeichen um mit der Ausgabe fortzusetzen
IXOFF  Einschalten des START/STOP - Eingabeprotokolls
IXON  Einschalten des START/STOP - Ausgabeprotokolls
PARMRK  Markieren von Partitätsfehler

Kommen wir nun zu den Werten des Ausgabe-Flag 'tcflag_t c_oflag' (Ausgabe-Flags)........

Konstante Bedeutung
BSDLY  Verzögerungsart für Backspace (BS0 oder BS1)
CRDLY  Verzögerungsart für CR (CR0,CR1,CR2,CR3)
FFDLY  Verzögerungsart für form-feed (FF0 oder FF1)
NLDLY  Verzögerungsart für NL (NL1 oder NL2)
OCRNL  Umwandeln von CR in NL
OFDEL  Auffüllzeichen ist DEL sonst NUL
OFILL  Auffüllzeichen anstatt einer zeitlichen Verzögerung
OLCUC Umwandeln von Klein-in Großbuchstaben
ONLCR Umwandeln von NL in CR
ONLRET Einstellen von NL auf CR
ONOCR  Unterdrücken von CR in Spalte 0
ONOEOT  Ignorieren von STRG+D
OPOST  Ein implemtierungsdefinierte Ausgabeart einschalten
OXTABS  Umwandeln von TAB in Leerzeichen
TABDLY  Verzögerungsart für horizontale Tabs (TAB0 bis TAB3)
VTDLY  Verzögerungsart für vertikale Tabs (VT0 und VT1)

Jetzt wollen wir uns anschauen welche Kontrollflags (tcflag_t c_cflag) wir verwenden können...

Konstante Bedeutung
CCTS_OFLOW  Einschalten des CTS-Ausgabeprotokolls
CIGNORE  Ignorieren von Kontroll-Flags
CLOCAL  Ausschalten der Modem-Steuerung
CREAD  Aktivieren des Empfängers
CRTS_IFLOW Einschalten des RTS-Eingabeprotokolls
CRTSCTS  Einschalten der Hardware-Flußkontrolle(RTS und CTS)
CSIZE  Bitanzahl für ein Zeichen (CS5 bis CS8)
CSTOPB Zwei Stop-Bits anstelle von einem senden
HUPCL  Verbindungsabbruch bei Beendigung des letzten Prozesses
MDMBUF Ausgabeprotokoll entsprechend dem Modem-Carrier-Flag
PARENB  Einschalten von Paritätsprüfung.
PARODD  Ungerade Parität, sonst gerade.

Als letztes noch ein Überblick zu den Lokalen Flags (tcflag_t c_lflag).......

Konstante Bedeutung
ECHO  Einschalten der ECHO - Funktion
ECHOCTL  Darstellung von Steuerzeichen als Zeichen
ECHOE  Gelöschte Zeichen mit Leerzeichen überschreiben
ECHOK  Zeichen löschen oder zur Neueingabe in neue Zeile positionieren
ECHOKE  Zeichen beim Löschen einer Zeile entfernen
ECHONL  Ausgabe von NL
ECHOPRT Ausgabe von gelöschten Zeichen für Hardcopy
FLUSHO  Leeren des Ausgabepuffer wie fflush()
ICANON  Zeilenorientierter Eingabemodus
IEXTEN  Einschalten des erweiterten Zeichensatzes für die Eingabe
ISIG  Sonderbedeutung von Terminal-Sonderzeichen einschalten
NOFLSH Abschalten des Leerens von Puffern bei INTR oder QUIT
NOKERNINFO  Ausschalten der Kern-Ausgabe bei STATUS
PENDIN  Neuausgabe von nichtverarbeitende Eingabezeichen
TOSTOP  Senden des Signals SIGTTOU bei der Ausgabe durch Hintergrundprozesse
XCASE  Umwandeln von eingegebenen Groß- in Kleinbuchstaben

So jetzt wollen sie aber sicherlich auch wissen wie sie die Terminal-Flags einsetzen können? Kommen wir also zu den ersten beiden Funktionen die in der Headerdatei <termios.h> definiert sind....

int tcgetattr(int fd, struct termios *terminal_zeiger);
int tcsetattr(int fd, int option, struct termios *terminal_zeiger);  

Wie man aus den Namen der Funktionen sicherlich bereits herauslesen kann dient tcgetattr() dazu die Attribute zu ermitteln und tcsetattr() die Attribute zu setzen. Für den Dateidesktiptor fd geben sie an was sie Manipulieren bzw. Abfragen wollen (0 oder SDTIN_FILENO(Standarteingabe) - 1 oder SDTOUT_FILENO (Standartausgabe)). Die Funktionen liefern beide bei Fehler -1 zurück ansonsten 0. Folgende Optionen können sie bei tcsetattr() angeben....

  • TCSANOW - Änderung wird sofort aktiv
  • TCSADRAIN - Änderung wird aktiv wenn alle Zeichen aus dem Puffer ausgegeben wurden
  • TCSAFLUSH - wie TCSADRAIN nur werden alle noch befindlichen Zeichen im Puffer verworfen

Um die Attribute eines Terminals abzufragen gehen sie folgt vor....

struct termios aktuell;

if(tcgetattr(fd, &aktuell) <0)
    {
      /*Fehler*/
     ....  

Das ganze jetzt in einem kurzem Beispiel.......

/*Download:term1.c*/
#include <stdio.h> #include <unistd.h> #include <termios.h> int main(int arg, char **argv) { struct termios aktuell; if(tcgetattr(STDIN_FILENO, &aktuell) <0) { printf("Kann die Abfrage: Standarteingabe Terminal nicht ausführen"); exit(0); } if(aktuell.c_iflag == BRKINT) printf("Taste BREAK bewirkt SIGINT\n"); if(aktuell.c_iflag != IMAXBEL) printf("Wenn Tasturpuffer voll gibt es kein akkustisches Signal\n"); return 0; }

Mit....

if(tcgetattr(STDIN_FILENO, &aktuell) >0)  

...fragen wir nach dem Attribut und mit unserer Variablen aktuell vom Typ struct termios können wir jetzt nach einzelnen Attributen fragen mittels........

if(aktuell.c_iflag == BRKINT)  

...ab. Hier fragen wir zum Beispiel ab ob das Flag BRKINT gesetzt ist (Beschreibung BRKINT siehe oben in der Tabelle).

Bevor ich Ihnen ein weiteres Beispiel zeige benötigen noch das Wissen einer Variablen in der Struktur termios die noch nicht zur Sprache kam. Das Array c_cc . Es enthält alle Sonderzeichen die durch das Programm verändert werden können.....

Konstante Bedeutung
VEOF  Dateiende
VEOL Zeilenende
VERASE letztes Zeichen löschen
VINTR  Unterbrechungssignal SIGINT
VKILL  Zeile löschen
VQUIT  Abbruch ala SIGQUIT
VSTOP  Ausgabe anhalten
VSTART Ausgabe fortsetzen
VSTATUS Statusinformationen anfordern
VSUSP  Einen Prozess suspendieren
VWERASE  Letztes Wort löschen
VMIN  Anzahl der Bytes die gelesen werden müssen bevor read() zurückkehrt


Weiter Eingabezeichen finden sie unter /usr/include/termbits.h oder /usr/include/asm/termbits.h
Wenn sie z.B. das Sonderzeichen EOF (STRG+C) ändern wollen gehen sie wie folgt vor....

/*Download:term2.c*/
#include <stdio.h> #include <unistd.h> #include <termios.h> int main() { struct termios term; int c; if((tcgetattr(STDIN_FILENO, &term)) <0) { printf("Fehler bei tcgetattr.......\n"); exit(0); } term.c_cc[VEOF] = 27; /*ASCII-Code 27 = ESC == EOF*/ if((tcsetattr(STDIN_FILENO, TCSAFLUSH, &term)) <0) { printf("Fehler bei tcsetattr........\n"); exit(1); } while((c=getchar()) != EOF) putchar(c); return 0; }

Bei diesem Beispiel haben wir das Sonderzeichen EOF verändert. Durch...

term.c_cc[VEOF] = 27;  

...bekommt unser Sonderzeichen EOF (VEOF) den ASCII-Code 27 zugewiesen der das Escape-Zeichen darstellt. Mit....

if((tcsetattr(STDIN_FILENO, TCSAFLUSH, &term)) >0)  

setzen wir unser Attribut in Kraft. Jetzt folgt die Eingabe durch.....

while((c=getchar()) != EOF)
      putchar(c);  

Sollange bis wir EOF betätigen. In unserem Beispiel wäre das jetzt die Escape (ESC)- Taste anstatt wie gewohnt STRG+C.
Da nicht jeder sämtlich ASCII-Code Zeichen im Kopf hat ist in der Headerdatei <termios.h> noch folgendes definiert....

#ifndef CTRL
      #define CTRL(ch) ((ch)&0x1F)
#endif  

Falls dies nicht bei Ihnen vorhanden sein sollte so wissen sie ja jetzt wie sie es selbst definieren können. Somit können ein Eingabe Zeichen wie STRG+Y folgendermaßen festlegen....

term.c_cc[VEOF] = CTRL('Y');  

Jetzt nur noch kurz wie sie die einzelnen Flags die sie oben in der Tabelle kennengelernt haben für c_iflag,c_oflag,c_cflag und c_lflag setzen bzw. löschen können....

Flag(s) setzen:

c_iflag | <flag>               //einzelnes flag setzen
c_iflag | <flag1|flag2|flag3>  //mehrere flags setzen auch mit der ODER Verknüpfung

Flag(s) löschen:

c_iflag & ~<flag>               //einzelnes Flag löschen
c_iflag & ~<flag1|flag2|flag3>  //mehrere Flags löschen  

Nun ein etwas längeres Beispiel......

/*Download:term3.c*/
#include <stdio.h> #include <unistd.h> #include <termios.h> enum{ERROR=-1,SUCCESS,ONEBYTE}; static struct termios BACKUP_TTY; /*Altes Terminal wiederherstellen*/ /*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ /*Eingabekanal wird so umgeändert damit die Tasten einzeln*/ /*abgefragt werden können*/ int new_tty(int fd) { struct termios buffer; /*Wir erfragen nach den Attributen des Terminals und übergeben diese*/ /*dann an buffer. BACKUP_TTY dient bei Programmende zur wiederherstellung*/ /* der alten Attribute und bleibt somit unberührt.*/ if((tcgetattr(fd, &BACKUP_TTY)) == ERROR) return ERROR; buffer = BACKUP_TTY; /*Lokale Flags werden gelöscht : ECHO = Zeichenausgabe auf Bildschirm*/ /* ICANON = Zeilenorientierter Eingabemodus*/ /* ISIG = Terminal Steuerzeichen */ buffer.c_lflag = buffer.c_lflag & ~(ECHO|ICANON|ISIG); /*VMIN=Anzahl der Bytes die gelesen werden müssen, bevor read() zurückkehrt*/ /* In unserem Beispiel 1Byte für 1 Zeichen*/ buffer.c_cc[VMIN] = 1; /*Wir setzen jetzt die von uns gewünschten Attribute*/ if((tcsetattr(fd, TCSAFLUSH, &buffer)) == ERROR) return ERROR; return SUCCESS; } /*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ /*Ursprüngliches Terminal wiederherstellen*/ int restore_tty(int fd) { if((tcsetattr(fd, TCSAFLUSH, &BACKUP_TTY)) == ERROR) return ERROR; return SUCCESS; } /*xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ int main(int argc, char **argv) { int rd; char c, buffer[10]; /*Setzen des neuen Modus*/ if(new_tty(STDIN_FILENO) == ERROR) { printf("Fehler bei der Funktion new_tty().....\n"); exit(0); } /*Erste Zeichen lesen*/ if(read(STDIN_FILENO, &c, 1) < ONEBYTE) { printf("Fehler bei read.....\n"); restore_tty(STDIN_FILENO); exit(0); } /*Haben wir ein ESC ('\E') gelesen? */ if(c==27) { /*Jep eine Escape-Sequenz, wir wollen den Rest*/ /* der Zeichen auslesen*/ rd=read(STDIN_FILENO, buffer, 4); buffer[rd]='\0'; /*String terminieren*/ /*Folgende Werte haben die Funktionstasten in der Term */ /* F1 = \E[[A */ /* F2 = \E[[B */ /* PFEIL RECHTS= \E[C */ /* PFEIL LINKS = \E[D */ /* PFEIL RUNTER= \E[B */ /* PFEIL HOCH = \E[A */ /* POS 1 = \E[1~ */ /* BILD RUNTER = \E[6~ */ /* BILD HOCH = \E[5~ */ if(strcmp(buffer,"[[A") == SUCCESS) printf("F1\n"); if(strcmp(buffer,"[[B") == SUCCESS) printf("F2\n"); if(strcmp(buffer,"[C") == SUCCESS) printf("->\n"); if(strcmp(buffer,"[D") == SUCCESS) printf("<-\n"); if(strcmp(buffer,"[B") == SUCCESS) printf("V\n"); if(strcmp(buffer,"[A") == SUCCESS) printf("^\n"); if(strcmp(buffer,"[1~") == SUCCESS) printf("POS 1\n"); if(strcmp(buffer,"[6~") == SUCCESS) printf("BILD RUNTER\n"); if(strcmp(buffer,"[5~") == SUCCESS) printf("BILD HOCH\n"); /*Nein kein ESC..............*/ } else { if((c<32) || (c==127)) printf("%d\n",c); /*Numerischen Wert Ausgeben*/ else printf("%c\n",c); /*Zeichen ausgeben*/ } restore_tty(STDIN_FILENO); return SUCCESS; }

Da ich das Programm ausführlich Dokumentiert habe möchte ich dazu nicht mehr viel Worte verlieren. Nur sollten sie zur Ausführung ein ECHTES Terminal öffnen sonst kann es passieren wenn sie z.B. die Taste F1 drücken gar nichts ausgegeben wird. Also wenn sie jetzt unter X arbeiten drücken sie die Tasten STRG+ALT+F1 und starten sie dann von dem echten Terminal das Programm.

Jetzt kommen wir zu einem Programm was häufig in Diskussionsforen etc. gestellt wird. Wie kann ich unter Linux/Unix eine Taste abfragen oder abfangen. Zuerst müssen wir das Terminal in den raw-Modus schalten. Ich habe das Programm ausführlich Dokumentiert....

/*Download:term4.c*/
#include <stdio.h> #include <unistd.h> #include <termios.h> enum{ERROR=-1, SUCCESS}; static struct termios new_io; static struct termios old_io; /*Funktion schaltet das Terminal in den raw-Modus:*/ /*Folgende Eingabeflags werden gelöscht : BRKINT, ICRNL, INPCK, ISTRIP, IXON*/ /*Folgende Kontrollflags werden gelöscht: CSIZE, PERENB*/ /*Folgende Ausgabeflags werden gelöscht : OPOST*/ /*Folgende Kontrollflags werden gelöscht: ECHO, ICANON, IEXTEN, ISIG*/ /*Gesetzt wird das Kontrollflag CS8 was Bedeuteted das ein Zeichen 8 Bit breit ist*/ /*Steuerzeichen : Leseoperation liefert 1 Byte VMIN=1 VTIME=1 */ int raw(int fd) { /*Sichern unseres Terminals*/ if((tcgetattr(fd, &old_io)) == ERROR) return ERROR; new_io = old_io; /*Wir verändern jetzt die Flags für den raw-Modus*/ new_io.c_iflag = new_io.c_iflag & ~(BRKINT|ICRNL|INPCK|ISTRIP|IXON); new_io.c_oflag = new_io.c_iflag & ~(OPOST); new_io.c_cflag = new_io.c_cflag & ~(CSIZE|PARENB); new_io.c_lflag = new_io.c_lflag & ~(ECHO|ICANON|IEXTEN|ISIG); new_io.c_cflag = new_io.c_cflag | CS8; new_io.c_cc[VMIN] = 1; new_io.c_cc[VTIME]= 0; /*Jetzt setzten wir den raw-Modus*/ if((tcsetattr(fd, TCSAFLUSH, &new_io)) == ERROR) return ERROR; return SUCCESS; } /*Funktion zur Abfrage einer Taste*/ int getch() { int c; if(raw(STDIN_FILENO) == ERROR) { printf("Fehler bei der Funktion raw......\n"); exit(0); } c = getchar(); /*Alten Terminal-Modus wiederherstellen*/ tcsetattr(STDIN_FILENO, TCSANOW, &old_io); return c; } int main() { int zeichen; printf("Bitte 'q' drücken um das Programm zu beenden!\n"); while((zeichen=getch()) != 'q'); return 0; }

Unsere Funktion raw() schaltet unser Terminal in den raw-Modus und mit unseren Funktion getch() können wir dann nach einer einzelnen oder irgendeiner Taste abfragen. Den großen Overhead der Funktion raw() hätten wir uns sparen können, da auch Linux/Unix dafür eine Funktion für uns bereithält.......

int cfmakeraw(struct termios *tty_zeiger);  

Diese Funktion die ebenfalls in der Headerdatei <termios.h> definiert und damit ist es uns einfacher möglich das Terminal in den raw-Modus zu setzen. Wollen wir das Beispiel mal auf unser Programm anwenden......

/*Download:term5.c*/
#include <stdio.h> #include <unistd.h> #include <termios.h> enum{ERROR=-1,SUCCESS}; typedef struct termios TTY; int kbhit() { TTY new_io, old_io; int c; if((tcgetattr(STDIN_FILENO, &old_io)) == SUCCESS) { cfmakeraw(&new_io); //setzen den raw-Modus für new_io tcsetattr(STDIN_FILENO, TCSANOW, &new_io); } else { printf("Konnte den raw-Modus nicht setzen!!!\n"); exit(0); } c = getchar(); /*Ürspüngliche Eigenschaft des Terminals wieder herstellen*/ tcsetattr(STDIN_FILENO, TCSANOW, &old_io); return c; } int main() { printf("Bitte Taste drücken!!\n"); while(kbhit() == SUCCESS); printf("Danke\n"); return 0; }

Natürlich will ich Ihnen nicht vorenthalten wie sie unser Terminal in den cbreak-Modus schalten können. Im cbreak-Modus müssen wir ledeglich die beiden lokalen Flags zur Ausgabe ECHO und den kanonischen Modus ICANON löschen oder genauer die Bits auf 0 setzen. Im cbreak-Modus haben sie wieder die Möglichkeit Steuerzeichen zu verwenden (z.B. STRG-C)......

/*Download:term6.c*/
#include <stdio.h> #include <unistd.h> #include <termios.h> enum{ERROR=-1, SUCCESS}; static struct termios new_io; static struct termios old_io; /*Funktion schaltet das Terminal in den cbreak-Modus: */ /* Kontrollflag ECHO und ICANON auf 0 setzen */ /* Steuerzeichen : Leseoperation liefert 1 Byte VMIN=1 VTIME=1 */ int cbreak(int fd) { /*Sichern unseres Terminals*/ if((tcgetattr(fd, &old_io)) == ERROR) return ERROR; new_io = old_io; /*Wir verändern jetzt die Flags für den cbreak-Modus*/ new_io.c_lflag = new_io.c_lflag & ~(ECHO|ICANON); new_io.c_cc[VMIN] = 1; new_io.c_cc[VTIME]= 0; /*Jetzt setzten wir den cbreak-Modus*/ if((tcsetattr(fd, TCSAFLUSH, &new_io)) == ERROR) return ERROR; return SUCCESS; } /*Funktion zur Abfrage einer Taste*/ int getch_cbreak() { int c; if(cbreak(STDIN_FILENO) == ERROR) { printf("Fehler bei der Funktion cbreak......\n"); exit(0); } c = getchar(); /*Alten Terminal-Modus wiederherstellen*/ tcsetattr(STDIN_FILENO, TCSANOW, &old_io); return c; } int main() { int zeichen; printf("Bitte 'q' drücken um das Programm zu beenden!\n"); while((zeichen=getch_cbreak()) != 'q'); return 0; }

ein Kapitel zurück          nach oben           ein Kapitel weiter


© 2001,2002 Jürgen Wolf