1 / 53

Terminal Control

Terminal Control. Terminal Control may seem like an arcane subject, but …. It illustrates the relationship between devices and files. The terminal driver is an easy and fun device driver to work with. Consider the following code: #include <stdio.h> int main ( ) { int c, n = 0;

cili
Download Presentation

Terminal Control

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Terminal Control

  2. Terminal Control may seem like an arcane subject, but … It illustrates the relationship between devices and files The terminal driver is an easy and fun device driver to work with

  3. 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)

  4. The ASCII Code Table

  5. Some Observations The program does not process any data until the Enter key is hit. The enter key generates a Carriage Return character, 13 but the program receives the character code 10, New Line.

  6. The Terminal Driver TerminalDriver Application The Terminal driver is doing some manipulation of the data as it flows between the terminal and your program!

  7. The Terminal Driver TerminalDriver Application attributes These manipulations are controlled by terminal attributes that can be changed by a process.

  8. Terminal Attributes To see the current set of terminal attributes stty stty -a

  9. Local mode flags: * icanon: enable/disable canonical mode * isig: enable/disable checking for INTR, SUSP, QUIT * echo: echo every character typed

  10. Input mode flags: * inlcr: map/do not map NLto CR on input * igncr: ignore/do not ignore CR on input * icrnl: map/do not map CR to NL on input

  11. Output mode flags: * onlcr: map/do not map NLto CR on output * ocrnl: map/do not map CR to NL

  12. Contol Characters:

  13. $ stty -a speed 9600 baud; 24 rows; 80 columns; . . . iflags: -istrp icrnl -inlcr . . . convert cr to nl - the flag is turned off man stty to see more detail

  14. You can alter a setting with the stty command stty -echo This turns off echo mode

  15. Terminal Modes Canonical or cooked mode The terminal driver stores incoming characters in a buffer Sends characters to the application a line at a time (when you press Enter) Handles basic editing functions (delete, backspace, …)

  16. Terminal Modes canonical mode TerminalDriver Application buffer lines characters Process Backspace, etc

  17. Terminal Modes Non-Canonical or cr-break mode The terminal driver does not buffer keyboard 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

  18. Terminal Modes non-canonical mode TerminalDriver Application characters characters Process Ctrl-C, CR-NL

  19. Terminal Modes Raw mode The terminal driver does not buffer keyboard input. Sends characters to the application a character at a time Does no character processing

  20. Terminal Modes raw mode TerminalDriver Application

  21. The Terminal Driver You control the Terminal driver by manipulating A set of terminal attributes stored in the device driver. TerminalDriver Application driver attributes tcgetattr( ) tcsetattr( )

  22. Reading attributes from the Terminal 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 stdin address of a termios struct

  23. Setting attributes in the Terminal 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 when to apply the settings zero for stdin address of a termios struct TCSANOW – immediately TCSADRAIN – after draining queued data TCSAFLUSH – after draining + flush input Note: Some shells will reset these attributes in an effort to protect you from yourself.

  24. The 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 */ };

  25. termios Flags Each flag is a bit in one of the mode fields. All of these flags have symbolic constants. To see all of the fields in the termios structure see termios man pages. These are the ones we are interested in. c_lflag ECHO – enable echo ICANON – canonical mode ISIG – enable signals

  26. Masking Bits in a termios Field

  27. Remember your boolean logic? Bitwise Operators & and | or ~ complement a b a & b a b a | b 1 1 1 1 0 0 0 1 0 0 0 0 1 1 1 1 0 1 0 1 1 0 0 0

  28. To Set a Flag flag = flag | mask 0’s except for the bits to be set in the flag flag mask flag | mask 1 1 1 1 0 1 0 1 1 0 0 0 this bit got set

  29. To Set a Flag 0 1 1 0 Flags Suppose I want to set this bit Mask What goes in the mask and what operation do I use?

  30. To Clear a Flag flag = flag & ~mask 1’s except for the bits to be cleared in the flag flag mask ~ mask flag & ~mask 1 1 0 0 1 0 1 1 0 1 0 0 0 0 1 0 this bit got cleared

  31. To Clear a Flag 0 1 1 0 Flags Suppose I want to clear this bit Mask What goes in the mask and what operation do I use?

  32. To Test a Flag if ( flag == flag & mask ) set the bits in the mask that you want to test in the flag flag mask flag & mask 1 1 1 1 0 0 0 1 0 0 0 0 Remember that in C, 0 is false and non-zero is true.

  33. To Test a Flag 0 1 1 0 Flags Suppose I want to know what this bit is Mask What goes in the mask and what operation do I use?

  34. Examine Echo flag #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 descriptor is 0 for stdin Example test the flag echostate.c

  35. Change Echo flag Example 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 ); } set the flag clear the flag

  36. Warning When you start messing with the terminal control flags from within a program you can get yourself into a state where you don’t know what the flags are … be careful.

  37. Writing a Program with Terminal Control

  38. Consider the following program structure Molay chapter 6 do some work ask if user wants to do more get response yes no

  39. By default the terminal is in canonical mode, so 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.

  40. What can we do so that the user does not have to hit the Enter key to input a response?

  41. do some work turn off canonical mode ask if user wants to do more get response turn on canonical mode yes response ? no

  42. This works great, but we still have to reply to every illegal keystroke -- annoying! The solution: Turn off echo mode and ignore illegal keystrokes.

  43. What if this program was running in an atm 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.

  44. Blocking vs Non-blocking I/O read The normal read operation waits until the read operation is satisfied before going on to the next instruction. do something

  45. Blocking vs Non-blocking I/O It is possible to use fcntl or open to change The properties of a file so that when the file is read, the program does not wait, for the read to finish, but goes on immediately to the next instruction. The read instruction returns a 0 if no data has been read. read do something

  46. 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 descriptor F_GETFD - get the file descriptor flags F_SETFD - set the file descriptor flags F_GETFL - get the file status flags F_SETFL - set the file status flags . . .

  47. File status flags O_RDONLY open file for reading only O_WRONLY open file for writing only O_RDWR open for reading and writing O_APPEND append on each write O_NONBLOCK non-blocking mode O_SYNC wait for writes to complete O_ASYNC asynchronous I/O (bsd and 4.3)

  48. 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 flag save the new flags

  49. 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

  50. 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 the buffer until it sees a newline or until the program tries to read. and the read doesn’t happen until here. timeout

More Related