140 likes | 385 Views
Implementing ‘noecho’. Programming details regarding the Linux implementation for ‘struct termios’ objects. Basic issues to consider. Normal tty operation is ‘canonical’ mode Input gets processed one line at a time Line-editing is allowed (e.g., backspace)
E N D
Implementing ‘noecho’ Programming details regarding the Linux implementation for ‘struct termios’ objects
Basic issues to consider • Normal tty operation is ‘canonical’ mode • Input gets processed one line at a time • Line-editing is allowed (e.g., backspace) • User’s keystrokes echoed to the screen • In C/C++ demo we could turn off echoing • We used two standard interface functions: • int tcgetattr( int fileno, struct termios *tty ); • Int tcsetattr( int fileno, int flag, struct termios *tty );
Basic Algorithm • Save a copy of the initial terminal settings • Modify certain bits in the ‘c_lflag’ field: • Turn off the ECHO bit, and • Turn on the ECHONL bit • Install the modified terminal settings • Perform desired echo-free keyboard input • Then reinstall the original terminal settings
How much storage space? • We must reserve adequate space for storing the initial terminal settings • But we don’t know how big this object is • This issue was transparently handled for us in our ‘noecho.cpp” demo by including: • #include <termios.h> • struct termios save_termios; • How can we accomplish this in assembly?
The ‘c_lflag’ field • We needed to modify bits in ‘c_lflag’ field • Those bits were represented by constants: ECHO and ECHONL • Their values were defined in <termios.h> • We did not need to know the actual values • But header-file isn’t available in assembly • So now we do need to know these values • Another constant needed is TCSANOW
Memory addressing • Where’s ‘c_lflag’ field within termios object • We can’t modify its bits until we know that • One idea is to study the Linux header-file • But where is it? There seem to be several • Nested type-declarations add to confusion • Another approach: let’s write a program to report the specific information we’ll need • Our ‘ttyinfo.cpp’ demo program shows us that sizeof( struct termios ) equals 60 bytes
.section .data # we need storage for two ‘termios’ objects origtty: .space 60 # original settings worktty: .space 60 # a ‘working copy’ # Insufficient space would cause big trouble! origtty worktty tcgetattr() does not know the size that we have allocated system would overwite part of the next data-area
Constants in assembly • We can use the .equ directive to create our own manifest constants: .equ ECHO, 0x00000008 .equ ECHONL, 0x00000040 .equ TCSANOW, 0x00000000 • Question: will our program also work on other versions of UNIX besides Linux?
Copying a structure object • We can create a program loop to copy the contents of a data-structure • Here again we need to know the number of bytes in the structure we want to copy • We can use a ‘counted loop’ to do copying • Three initialization steps: • put source-address in register %esi • put dest’n address in register %edi • put the byte-count into register %ecx • Advance %esi and %edi as each byte is copied
The actual loop code movl $origtty, %esi movl $worktty, %edi movl $60, %ecx again: movb (%esi), %al movb %al, (%edi) incl %esi incl %edi loop again
Modifying some flag bits • Determine offset of the ‘c_lflag’ field (=12) • Setup this offset in a CPU register (%edi) movl $12, %edi • Use AND-instruction to turn a bit off: andl $~ECHO, worktty(%edi) • Use OR-instruction to turn a bit on: orl $ECHONL, worktty(%edi) • (Here other approaches also are possible)
Non-canonical terminal modes • Certain kinds of applications do not lend themselves to ‘canonical’ terminal input • We may want an instant response to each individual keystroke (not to an entire line) • Example: computer game using keyboard • We can ‘turn off’ canonical line-processing • Very similar to ‘turning off’ the input echo i.e., worktty.c_lflag &= ~ICANON;
Two further adjustments • Need two changes in the c_cc[] array: worktty.c_cc[ VMIN ] = 1; worktty.c_cc[ VTIME ] = 0; • First change causes ‘read()’ function to return as soon as at least one character has been typed • Second change causes ‘read() function to return without any time-delay
An application • You could use this ‘non-canonical’ terminal mode to implement visual “user feedback” in your ‘password’ program • Whenever the user presses a new key, the program immediately responds by printing a neutral character (e.g. ‘*’) to confirm that it has indeed received the user’s input • Special handling for ‘backspace’ is needed • Suggestion: Try it first in a C/C++ program