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 again: movl movl movl movb movb incl incl loop $origtty, %esi $worktty, %edi $60, %ecx (%esi), %al %al, (%edi) %esi %edi 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