terminal control operating systems. terminal control may seem like an arcane subject, but … it...
Post on 19-Dec-2015
213 views
TRANSCRIPT
Terminal Control may seem like an arcane subject,but …
It illustrates the relationship between devices and files
The terminal driver is an easy device driver to work with
operatingsystems
Consider the following code:
#include <stdio.h>
int main ( ){ int c, n = 0;
while( ( c = getchar( ) ) != ‘Q’ ) printf ( “char %3d is %c code %d\n”, n++, c, c);
return 0;}
Run it ..... (listchars.c)
The program does not process any data until the Enter key is hit.
The enter key generates a Carriage Return character, 13but the program receives the character code 10, New Line.
Some Observations
Moreover, when the program outputs a New Line character,it outputs as a Carriage Return. New Line only move the cursordown one line, it does not move the cursor to the left margin!
Some Observations
The Terminal DriverThe Terminal DriverThe Terminal DriverThe Terminal Driver
TerminalDriver Application
operatingsystems
The Terminal driver is doing some manipulation of thedata as it flows between the terminal and your program!
The Terminal DriverThe Terminal DriverThe Terminal DriverThe Terminal Driver
TerminalDriver Application
operatingsystems
These manipulations are controlled by terminal attributesthat can be changed by a process.
attributes
$ stty -a
speed 9600 baud; 24 rows; 80 columns; . . . iflags: -istrp icrnl -inlcr . . .
input flags: what the driver does with characters coming from the terminal
- the flag is turned off
convert cr to nl
man stty to see more detail
Terminal ModesTerminal ModesTerminal ModesTerminal Modes
Canonical or cooked mode
The terminal driver stores incoming characters in a buffer
Sends characters to the application a line at a time
Handles basic editing functions (delete, backspace, …)
operatingsystems
The Terminal DriverThe Terminal DriverThe Terminal DriverThe Terminal Driver
TerminalDriver
Application
operatingsystems
characters lines
canonical mode
buffer
ProcessBackspace, etc
Terminal ModesTerminal ModesTerminal ModesTerminal Modes
Non-Canonical or cr-break mode
The terminal driver does not bufferkeyboard input
Sends characters to the application a character at a time, as it is entered
Does some character processing * Ctrl-C (interrupt) * carriage return to newline
operatingsystems
The Terminal DriverThe Terminal DriverThe Terminal DriverThe Terminal Driver
TerminalDriver
Application
operatingsystems
non-canonical mode
characters characters
ProcessCtrl-C, CR-NL
Terminal ModesTerminal ModesTerminal ModesTerminal Modes
Raw mode
The terminal driver does not bufferkeyboard input.
Sends characters to the application a character at a time
Does no character processing
operatingsystems
The Terminal DriverThe Terminal DriverThe Terminal DriverThe Terminal Driver
TerminalDriver Application
operatingsystems
raw mode
The Terminal DriverThe Terminal DriverThe Terminal DriverThe Terminal Driver
TerminalDriver
Application
operatingsystems You control the Terminal driver by manipulating
A set of terminal attributes stored in the device driver.
tcgetattr( ) tcsetattr( )
driver attributes
Reading Attributes from the Reading Attributes from the Terminal DriverTerminal Driver
Reading Attributes from the Reading Attributes from the Terminal DriverTerminal Driver
#include <termios.h>#include <unistd.h>
int result = tcgetattr(int fd, struct termios* attrs);
returns 0 if successful -1 if an error
zero for stdinaddress of atermios struct
operatingsystems
Setting Attributes in the Setting Attributes in the Terminal DriverTerminal Driver
Setting Attributes in the Setting Attributes in the Terminal DriverTerminal Driver
#include <termios.h>#include <unistd.h>
int result = tcsetattr(int fd, int when, struct termios* attrs);
returns 0 if successful -1 if an error
zero for stdinaddress of atermios struct
when toapply thesettings
TCSANOW – immediatelyTCSADRAIN – after draining queued dataTCSAFLUSH – after draining + flush input
operatingsystems
Note: Some shells will reset theseattributes in an effort to protectyou from yourself.
The termios structThe termios structThe termios structThe termios struct
struct termios{ tcflag_t c_iflag; /* input mode flags */ tcflag_t c_oflag; /* output mode flags */ tcflag_t c_cflag; /* control mode flags */ tcflag_t c_lflag; /* local mode flags */ cc_t c_cc[NCCS]; /* control characters */ speed_t c_ispeed; /* input speed */ speed_t c_ospeed; /* output speed */};
operatingsystems
flagsflagsflagsflags
c_lflag
ISIG – enable signals
ICANON – canonical mode
ECHO – enable echo
operatingsystems
All of these flags have symbolic constants. To see all of the fields in the termios structure see termios man pages.
Bitwise OperatorsBitwise OperatorsBitwise OperatorsBitwise Operators
& and| or~ complement
1 1 11 0 00 1 00 0 0
a b a & b
1 1 11 0 10 1 10 0 0
a b a | b
operatingsystems
Remember your boolean logic?
To Set a flagTo Set a flagTo Set a flagTo Set a flag
flag = flag | mask
0’s except for the bits to be set in the flag
1 1 11 0 10 1 10 0 0
flag mask flag | mask
operatingsystems
this bit got set
To Clear a flagTo Clear a flagTo Clear a flagTo Clear a flag
flag = flag & ~mask
1’s except for the bits to be cleared in the flag
1 1 0 01 0 1 10 1 0 00 0 1 0
flag mask ~ mask flag & ~mask
operatingsystems
this bit got cleared
To Test a flagTo Test a flagTo Test a flagTo Test a flag
if ( flag == flag & mask )
1 1 11 0 00 1 00 0 0
flag mask flag & mask
operatingsystems
Remember that in C, 0 is false and non-zerois true.
set the bits in the mask that you want to test inthe flag
if ( flag & mask )
ExampleExampleExampleExampleoperatingsystems
#include <stdio.h>#include <termios.h>#include <stdlib.h>int main ( ){ struct termios info; int rv; if ( (rv = tcgetattr( 0, &info ) ) == -1 ) { perror(“tcgetattr error”); exit ( 1 ); } if ( info.c_lflag & ECHO) printf(“ echo flag is set\n”); else printf(“ echo flag is not set\n”);
return 0;}
file descriptoris 0 for stdin
Examine Echo flag
test the flag
Run ... echostate.c
ExampleExampleExampleExampleoperatingsystems
if ( (rv = tcgetattr( 0, &info ) ) == -1 ) { perror(“tcgetattr error”); exit ( 1 ); } if ( argv[1][0] == ‘y’ ) info.c_lflag |= ECHO; else info.c_lflag &= ~ECHO; if ( tcsetattr ( 0, TCSANOW, &info ) == -1) { perror(“tcsetattr error”); exit ( 1 ); }
Change Echo flag
set the flag
clear the flag
Run ... setecho.c
Writing a Terminal ProgramWriting a Terminal ProgramWriting a Terminal ProgramWriting a Terminal Programoperatingsystems
do some work
ask if user wants to do
more
getresponse
no
yes
Molay chapter 6
operatingsystems
Because the terminal is in canonical mode,The user has the following problems:
1. The user has to press the enter key before the program can act on the input.
2. The user can type something other than ‘y’ or ‘n’ and nothing happens.
operatingsystems
do some work
ask if user wants to do
more
no
yes
turn off canonical
mode
turn on canonical
mode
get response
response?
operatingsystems
This works great, but replying to everyillegal keystroke is annoying!
The solution: Turn off echo mode andignore illegal keystrokes.
operatingsystems
What if this program was running in anatm machine, and the person walked away without typing ‘y’ or ‘n’?
Someone else could walk up and run a transaction using this person’s account.
operatingsystems Blocking vs Non-blocking I/O
read
do something
The normal read operation waitsuntil the read operation is satisfiedbefore going on to the next instruction.
operatingsystems Blocking vs Non-blocking I/O
read
do something
It is possible to use fcntl or open to change the properties of a file so thatwhen the file is read, the programdoes not wait for the read to finish,but goes on immediately to the nextinstruction.
The read instruction returns a 0 if nodata has been read.
Using fcntl( )Using fcntl( )Using fcntl( )Using fcntl( )
#include <sys/types.h>#include <unistd.h>#include <fcntl.h>
int fcntl(int filedes, int cmd, … /* int arg */);
F_DUPFD - duplicate the file descriptorF_GETFD - get the file descriptor flagsF_SETFD - set the file descriptor flagsF_GETFL - get the file status flagsF_SETFL - set the file status flags . . .
File status flagsFile status flagsFile status flagsFile status flags
O_RDONLY open file for reading onlyO_WRONLY open file for writing onlyO_RDWR open for reading and writing
O_APPEND append on each writeO_NONBLOCK non-blocking modeO_SYNCwait for writes to completeO_ASYNC asynchronous I/O (bsd and 4.3)
void set_nodelay_mode( ){ int termflags;
termflags = fcntl(0, F_GETFL); termflags |= NONBLOCK; fcntl(0, F_SETFL, termflags);}
get the file descriptor flags
set non-blocking flagsave the new flags
operatingsystems
int get response(char* question, int maxtries){ int input; printf(“%s (y/n)?”, question); flush (stdout); while (1) { sleep(SLEEPTIME); input = tolower(get_ok_char( ) ); if ( input == ‘y’ ) return 1; if ( input == ‘n’ ) return 0; if ( maxtries -- == 0) return 2; }}
print the question
operatingsystems
int get response(char* question, int maxtries){ int input; printf(“%s (y/n)?”, question); flush (stdout); while (1) { sleep(SLEEPTIME); input = tolower(get_ok_char( ) ); if ( input == ‘y’ ) return 1; if ( input == ‘n’ ) return 0; if ( maxtries -- == 0) return 2; }}
The o/s won’t flush thebuffer until it sees a newline oruntil the program tries to read.
and the read doesn’thappen until here.
timeout
operatingsystems
char get_ok_char( ){ int c: while ( ( c = getchar( ) ) != EOF && strchr(“YyNn”, c) == NULL);
return c;}
Drops out if EOF is returned.Note that when read is non-blocking an EOF is returned when there is no data.
In this case, the EOF ( 0 ) gets returned.
operatingsystems
char get_ok_char( ){ int c: while ( ( c = getchar( ) ) != EOF && strchr(“YyNn”, c) == NULL);
return c;}
Or it drops out when one of‘Y’, ‘y’, ‘N’, or ‘n’ is typed.
In this case, the typed character is returned.
The strchr( str1, c) function looks for the character c in the string str1. It returns a pointer to the character or NULL if the character is not found.
Your more command should work as follows:
Your program will display the first 23 lines of the file. On the last line ofthe screen, it will then display the file name of the file being displayed, and the percentage of the file which has been displayed.
It then will wait for user input. The user has three choices at this point: If the user types a 'q', then your program exits. If the user types a space, then your program displays the next 23 lines of the file. If the user presses the ENTER key, then just the next line of the file is displayed.
Note that invalid keystrokes are ignored and keystrokes are not echoed back to the screen.
In the last two cases, your program should just display the percentage of the file that has been displayed. It only displays the file name on the first screen displayed. Don’t allow the file name and percentage to scrollup the screen as new lines of data from the file are displayed.