terminal control operating systems. terminal control may seem like an arcane subject, but … it...

43
Terminal Control Terminal Control operating systems

Post on 19-Dec-2015

213 views

Category:

Documents


0 download

TRANSCRIPT

Terminal ControlTerminal ControlTerminal ControlTerminal Control

operatingsystems

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

Terminal Attributes

To see the current set of terminal attributes

stty

stty -a

$ 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

You can alter setting with the stty command

stty -echo

This turns off echo mode

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.

MaskingMaskingMaskingMasking

operatingsystems

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.