|
![ein Kapitel weiter](../weiter.gif)
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 weiter](../weiter.gif)
© 2001,2002 Jürgen Wolf
|