Implementing ‘noecho’ Programming details regarding the Linux implementation for ‘struct...

14
Implementing ‘noecho’ Programming details regarding the Linux implementation for ‘struct termios’ objects

Transcript of Implementing ‘noecho’ Programming details regarding the Linux implementation for ‘struct...

Page 1: Implementing ‘noecho’ Programming details regarding the Linux implementation for ‘struct termios’ objects.

Implementing ‘noecho’

Programming details regarding the Linux implementation for

‘struct termios’ objects

Page 2: 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 );

Page 3: Implementing ‘noecho’ Programming details regarding the Linux implementation for ‘struct termios’ objects.

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

Page 4: Implementing ‘noecho’ Programming details regarding the Linux implementation for ‘struct termios’ objects.

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?

Page 5: Implementing ‘noecho’ Programming details regarding the Linux implementation for ‘struct termios’ objects.

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

Page 6: Implementing ‘noecho’ Programming details regarding the Linux implementation for ‘struct termios’ objects.

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

Page 7: Implementing ‘noecho’ Programming details regarding the Linux implementation for ‘struct termios’ objects.

.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

system would overwite part of the next data-area

tcgetattr() does notknow the size thatwe have allocated

Page 8: Implementing ‘noecho’ Programming details regarding the Linux implementation for ‘struct termios’ objects.

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?

Page 9: Implementing ‘noecho’ Programming details regarding the Linux implementation for ‘struct termios’ objects.

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

Page 10: Implementing ‘noecho’ Programming details regarding the Linux implementation for ‘struct termios’ objects.

The actual loop code

movl $origtty, %esimovl $worktty, %edimovl $60, %ecx

again: movb (%esi), %almovb %al, (%edi)incl %esiincl %ediloop again

Page 11: Implementing ‘noecho’ Programming details regarding the Linux implementation for ‘struct termios’ objects.

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)

Page 12: Implementing ‘noecho’ Programming details regarding the Linux implementation for ‘struct termios’ objects.

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 echoi.e., worktty.c_lflag &= ~ICANON;

Page 13: Implementing ‘noecho’ Programming details regarding the Linux implementation for ‘struct termios’ objects.

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

Page 14: Implementing ‘noecho’ Programming details regarding the Linux implementation for ‘struct termios’ objects.

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