Sehr Umfangreiche Webseite zum Programmieren in C Perl CGI, Skripting, Linux, Systemprogrammierung Terminal Konsole Terminal Ein/Ausgabe ioctlC C++ C/C++ ANSI C Linux Linuxsystemprogrammierung Linuxsystemprogrammieren Terminal Konsole Terminal Ein/Ausgabe ioctl 6. Terminal E/A

6.1. Terminalattribute (tcgetattr, tcsetattr)           zurück zum Inhaltsverzeichnis

Bevor Sie zur Terminal-Ein/Ausgabe kommen, muss ich Ihnen erst noch erklären, was es mit den Terminals überhaupt auf sich hat.

Terminals sind über serielle Schnittstelle mit Linux-Rechnern verbunden. Um Sie jetzt nicht zu verwirren, wenn Sie eine Konsole verwenden, arbeiten Sie in gleicher Weise, wie mit einer Terminalleitung, auch wenn keine 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 eines Terminals, sind in der Grundeinstellung immer Zeilengepuffert. read wird also erst beendet, wenn die ENTER-Taste gedrückt wurde. Drücken Sie stattdessen die Tastenkombination STRG+D, liefert read 0 (EOF) zurück. Dies bedeutet meist, die Beendigung des Programms. Dieses Verhalten kann mit mit O_NONBLOCK mit der Funktion open() oder nachträglich mit der Funktion fcntl() verändern.

Ein Tipp am Rande: Sie können einige gezeigt Möglichkeiten hier auch verwenden um zwei PC's mit einem Nullmodemkabel zu koppeln. Ein Nullmodemkabel können Sie an der seriellen Schnittstelle des jeweiligen PC's anhängen. Das Nullmodemkabel spielt jedem anderen Rechner vor er sei ein Modem. Dies gelingt in dem man die Anschlussbelegung 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.

Zugegeben, in der Zeit der GUI`s mag dieses Thema (Terminal-E/A) altertümlich erscheinen, aber wenn es um Netzwerk-Programmierung geht sind Terminals unschlagbar. Das Kapitel Terminal E/A handelt z.B. von solchen Themen:

Bevor Sie anfangen, folgen noch schnell die zwei Möglichkeiten die Ihnen für den Terminal-Modi zur Verfügung stehen:

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, in der Headerdatei <termios.h> definiert. 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 Sie noch die Kenntnis, welche Werte Sie mit 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


Jetzt wollen Sie aber 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 mit tcsetattr() angeben ...

Um nun die Attribute eines Terminals abzufragen, gehen Sie wie folgt vor ...

struct termios aktuell;

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

Das Ganze nun in einem kurzem Beispiel ...

#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)

... erfragen Sie nach dem Attribut der Standardeingabe und mit aktuell vom Typ struct termios können Sie jetzt die einzelnen Attributen abfragen mit ...

if(aktuell.c_iflag == BRKINT)

Hier fragen Sie 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 die Kenntnis 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

Weiter mit (Fortsetzung) 6.1. Terminalattribute (tcgetattr, tcsetattr)