Analytics cookies. We use analytics cookies to understand how you use our websites so we can make them better, e.g. They're used to gather information about the pages you visit and how many clicks you need to accomplish a task. The /usr/include/termios.hfile contains information used by subroutines that apply to terminal files. The definitions, values, and structures in this file are required for compatibility with the POSIX standard. The termios.hfile also supports ioctl modem-control.
Let's try and read keypresses from the user. (The lines you need to add arehighlighted and marked with arrows.)
read()
and STDIN_FILENO
come from . We are asking
read()
toread 1
byte from the standard input into the variable c
, and to keep doingit until there are no more bytes to read. read()
returns the number of bytesthat it read, and will return 0
when it reaches the end of a file.
When you run ./kilo
, your terminal gets hooked up to the standard input, andso your keyboard input gets read into the c
variable. However, by defaultyour terminal starts in canonical mode, also called cooked mode. Inthis mode, keyboard input is only sent to your program when the user pressesEnter. This is useful for many programs: it lets the user type in aline of text, use Backspace to fix errors until they get their inputexactly the way they want it, and finally press Enter to send it tothe program. But it does not work well for programs with more complex userinterfaces, like text editors. We want to process each keypress as it comes in,so we can respond to it immediately.
What we want is raw mode. Unfortunately, there is no simple switch you canflip to set the terminal to raw mode. Raw mode is achieved by turning off agreat many flags in the terminal, which we will do gradually over the course ofthis chapter.
To exit the above program, press Ctrl-D to tell read()
that it'sreached the end of file. Or you can always press Ctrl-C to signalthe process to terminate immediately.
Press q to quit?
To demonstrate how canonical mode works, we'll have the program exit when itreads a q keypress from the user. (Lines you need to change arehighlighted and marked the same way as lines you need to add.)
To quit this program, you will have to type a line of text that includes a q
in it, and then press enter. The program will quickly read the line of text onecharacter at a time until it reads the q
, at which point the while
loopwill stop and the program will exit. Any characters after the q
will be leftunread on the input queue, and you may see that input being fed into your shellafter your program exits.
Turn off echoing
We can set a terminal's attributes by (1) using tcgetattr()
to read thecurrent attributes into a struct, (2) modifying the struct by hand, and(3) passing the modified struct to tcsetattr()
to write the new terminalattributes back out. Let's try turning off the ECHO
feature this way.
struct termios
, tcgetattr()
, tcsetattr()
, ECHO
, and TCSAFLUSH
allcome from .
The ECHO
feature causes each key you type to be printed to the terminal, soyou can see what you're typing. This is useful in canonical mode, but reallygets in the way when we are trying to carefully render a user interface in rawmode. So we turn it off. This program does the same thing as the one in theprevious step, it just doesn't print what you are typing. You may be familiarwith this mode if you've ever had to type a password at the terminal, whenusing sudo
for example.
After the program quits, depending on your shell, you may find your terminal isstill not echoing what you type. Don't worry, it will still listen to what youtype. Just press Ctrl-C to start a fresh line of input to yourshell, and type in reset
and press Enter. This resets yourterminal back to normal in most cases. Failing that, you can always restartyour terminal emulator. We'll fix this whole problem in the next step.
Terminal attributes can be read into a termios
struct by tcgetattr()
. Aftermodifying them, you can then apply them to the terminal using tcsetattr()
.The TCSAFLUSH
argument specifies when to apply the change: in this case, itwaits for all pending output to be written to the terminal, and also discardsany input that hasn't been read.
The c_lflag
field is for 'local flags'. A comment in macOS's describes it as a 'dumping ground for other state'. So perhaps it should bethought of as 'miscellaneous flags'. The other flag fields are
c_iflag
(inputflags), c_oflag
(output flags), and c_cflag
(control flags), all of whichwe will have to modify to enable raw mode.
ECHO
is a bitflag, defined as00000000000000000000000000001000
in binary. We use the bitwise-NOT operator(~
) on this value to get 11111111111111111111111111110111
. We thenbitwise-AND this value with the flags field, which forces the fourth bit in theflags field to become 0
, and causes every other bit to retain its currentvalue. Flipping bits like this is common in C.
Disable raw mode at exit
Let's be nice to the user and restore their terminal's original attributes whenour program exits. We'll save a copy of the termios
struct in its originalstate, and use tcsetattr()
to apply it to the terminal when the programexits.
atexit()
comes from . We use it to register our
disableRawMode()
function to be called automatically when the program exits,whether it exits by returning from main()
, or by calling the exit()
function. This way we can ensure we'll leave the terminal attributes the waywe found them when our program exits.
We store the original terminal attributes in a global variable, orig_termios
.We assign the orig_termios
struct to the raw
struct in order to make a copyof it before we start making our changes.
You may notice that leftover input is no longer fed into your shell after theprogram quits. This is because of the TCSAFLUSH
option being passed totcsetattr()
when the program exits. As described earlier, it discards anyunread input before applying the changes to the terminal. (Note: This doesn'thappen in Cygwin for some reason, but it won't matter once we are reading inputone byte at a time.)
Turn off canonical mode
There is an ICANON
flag that allows us to turn off canonical mode. This meanswe will finally be reading input byte-by-byte, instead of line-by-line.
ICANON
comes from . Input flags (the ones in the
c_iflag
field) generally start with I
like ICANON
does. However, ICANON
is not aninput flag, it's a 'local' flag in the c_lflag
field. So that's confusing.
Now the program will quit as soon as you press q.
Display keypresses
To get a better idea of how input in raw mode works, let's print out each bytethat we read()
. We'll print each character's numeric ASCII value, as well asthe character it represents if it is a printable character.
iscntrl()
comes from , and
printf()
comes from .
iscntrl()
tests whether a character is a control character. Controlcharacters are nonprintable characters that we don't want to print to thescreen. ASCII codes 0–31 are all control characters, and 127 is also acontrol character. ASCII codes 32–126 are all printable. (Check out theASCII table to see all of the characters.)
printf()
can print multiple representations of a byte. %d
tells it toformat the byte as a decimal number (its ASCII code), and %c
tells it towrite out the byte directly, as a character.
This is a very useful program. It shows us how various keypresses translateinto the bytes we read. Most ordinary keys translate directly into thecharacters they represent. But try seeing what happens when you press the arrowkeys, or Escape, or Page Up, or Page Down, orHome, or End, or Backspace, orDelete, or Enter. Try key combinations withCtrl, like Ctrl-A, Ctrl-B, etc.
You'll notice a few interesting things:
- Arrow keys, Page Up, Page Down, Home, andEnd all input 3 or 4 bytes to the terminal:
27
,'['
, and thenone or two other characters. This is known as an escape sequence. Allescape sequences start with a27
byte. Pressing Escape sends asingle27
byte as input. - Backspace is byte
127
. Delete is a 4-byte escapesequence. - Enter is byte
10
, which is a newline character, also known as'n'
. - Ctrl-A is
1
, Ctrl-B is2
, Ctrl-C is…oh, that terminates the program, right. But the Ctrl keycombinations that do work seem to map the letters A–Z to the codes1–26.
By the way, if you happen to press Ctrl-S, you may find your programseems to be frozen. What you've done is you've asked your program to stopsending you output. PressCtrl-Q to tell it to resume sending you output.
Also, if you press Ctrl-Z (or maybe Ctrl-Y), your programwill be suspended to the background. Run the fg
command to bring it back tothe foreground. (It may quit immediately after you do that, as a result ofread()
returning -1
to indicate that an error occurred. This happens onmacOS, while Linux seems to be able to resume the read()
call properly.)
Turn off Ctrl-C and Ctrl-Z signals
By default, Ctrl-C sends a SIGINT
signal to the current processwhich causes it to terminate, and Ctrl-Z sends a SIGTSTP
signal tothe current process which causes it to suspend. Let's turn off the sending ofboth of these signals.
ISIG
comes from . Like
ICANON
, it starts with I
but isn't aninput flag.
Now Ctrl-C can be read as a 3
byte and Ctrl-Z can beread as a 26
byte.
This also disables Ctrl-Y on macOS, which is like Ctrl-Zexcept it waits for the program to read input before suspending it.
Disable Ctrl-S and Ctrl-Q
By default, Ctrl-S and Ctrl-Q are used forsoftware flow control.Ctrl-S stops data from being transmitted to the terminal until youpress Ctrl-Q. This originates in the days when you might want topause the transmission of data to let a device like a printer catch up. Let'sjust turn off that feature.
IXON
comes from . The
I
stands for 'input flag' (which it is,unlike the other I
flags we've seen so far) and XON
comes from the names ofthe two control characters that Ctrl-S and Ctrl-Qproduce: XOFF
to pause transmission and XON
to resume transmission.
Now Ctrl-S can be read as a 19
byte and Ctrl-Q can beread as a 17
byte.
Disable Ctrl-V
On some systems, when you type Ctrl-V, the terminal waits for you totype another character and then sends that character literally. For example,before we disabled Ctrl-C, you might've been able to typeCtrl-V and then Ctrl-C to input a 3
byte. We can turnoff this feature using the IEXTEN
flag.
Turning off IEXTEN
also fixes Ctrl-O in macOS, whose terminaldriver is otherwise set to discard that control character.
IEXTEN
comes from . It is another flag that starts with
I
butbelongs in the c_lflag
field.
Ctrl-V can now be read as a 22
byte, and Ctrl-O as a15
byte.
Fix Ctrl-M
If you run the program now and go through the whole alphabet while holding downCtrl, you should see that we have every letter except M.Ctrl-M is weird: it's being read as 10
, when we expect it to beread as 13
, since it is the 13th letter of the alphabet, andCtrl-J already produces a 10
. What else produces 10
? TheEnter key does.
It turns out that the terminal is helpfully translating any carriage returns(13
, 'r'
) inputted by the user into newlines (10
, 'n'
). Let's turnoff this feature.
ICRNL
comes from . The
I
stands for 'input flag', CR
standsfor 'carriage return', and NL
stands for 'new line'.
Now Ctrl-M is read as a 13
(carriage return), and theEnter key is also read as a 13
.
Turn off all output processing
It turns out that the terminal does a similar translation on the output side.It translates each newline ('n'
) we print into a carriage return followed bya newline ('rn'
). The terminal requires both of these characters in orderto start a new line of text. The carriage return moves the cursor back to thebeginning of the current line, and the newline moves the cursor down a line,scrolling the screen if necessary. (These two distinct operations originated inthe days of typewriters andteletypes.)
We will turn off all output processing features by turning off the OPOST
flag. In practice, the 'n'
to 'rn'
translation is likely the only outputprocessing feature turned on by default.
OPOST
comes from .
O
means it's an output flag, and I assumePOST
stands for 'post-processing of output'.
If you run the program now, you'll see that the newline characters we'reprinting are only moving the cursor down, and not to the left side of thescreen. To fix that, let's add carriage returns to our printf()
statements.
Termios.h Mingw
From now on, we'll have to write out the full 'rn'
whenever we wantto start a new line.
Miscellaneous flags
Let's turn off a few more flags.
BRKINT
, INPCK
, ISTRIP
, and CS8
all come from .
This step probably won't have any observable effect for you, because theseflags are either already turned off, or they don't really apply to modernterminal emulators. But at one time or another, switching them off wasconsidered (by someone) to be part of enabling 'raw mode', so we carry on thetradition (of whoever that someone was) in our program.
As far as I can tell:
- When
BRKINT
is turned on, abreak condition willcause aSIGINT
signal to be sent to the program, like pressingCtrl-C
. INPCK
enables parity checking, which doesn't seem to apply to modernterminal emulators.ISTRIP
causes the 8th bit of each input byte to be stripped, meaning itwill set it to0
. This is probably already turned off.CS8
is not a flag, it is a bit mask with multiple bits, which we set usingthe bitwise-OR (|
) operator unlike all the flags we are turning off. Itsets the character size (CS) to 8 bits per byte. On my system, it's alreadyset that way.
A timeout for read()
Currently, read()
will wait indefinitely for input from the keyboard beforeit returns. What if we want to do something like animate something on thescreen while waiting for user input? We can set a timeout, so that read()
returns if it doesn't get any input for a certain amount of time.
VMIN
and VTIME
come from . They are indexes into the
c_cc
field, which stands for 'control characters', an array of bytes that controlvarious terminal settings.
The VMIN
value sets the minimum number of bytes of input needed beforeread()
can return. We set it to 0
so that read()
returns as soon as thereis any input to be read. The VTIME
value sets the maximum amount of time towait before read()
returns. It is in tenths of a second, so we set it to 1/10of a second, or 100 milliseconds. If read()
times out, it will return 0
,which makes sense because its usual return value is the number of bytes read.
When you run the program, you can see how often read()
times out. If youdon't supply any input, read()
returns without setting the c
variable,which retains its 0
value and so you see 0
s getting printed out. If youtype really fast, you can see that read()
returns right away after eachkeypress, so it's not like you can only read one keypress every tenth of asecond.
If you're using Bash on Windows, you may see that read()
still blocks forinput. It doesn't seem to care about the VTIME
value. Fortunately, this won'tmake too big a difference in our text editor, as we'll be basically blockingfor input anyways.
Error handling
enableRawMode()
now gets us fully into raw mode. It's time to clean up thecode by adding some error handling.
First, we'll add a die()
function that prints an error message and exits theprogram.
perror()
comes from , and
exit()
comes from .
Include Termios H R
Most C library functions that fail will set the global errno
variable toindicate what the error was. perror()
looks at the global errno
variableand prints a descriptive error message for it. It also prints the string givento it before it prints the error message, which is meant to provide contextabout what part of your code caused the error.
After printing out the error message, we exit the program with an exit statusof 1
, which indicates failure (as would any non-zero value).
Let's check each of our library calls for failure, and call die()
when theyfail.
#include Sys/termios.h
errno
and EAGAIN
come from .
tcsetattr()
, tcgetattr()
, and read()
all return -1
on failure, and setthe errno
value to indicate the error.
In Cygwin, when read()
times out it returns -1
with an errno
of EAGAIN
,instead of just returning 0
like it's supposed to. To make it work in Cygwin,we won't treat EAGAIN
as an error.
An easy way to make tcgetattr()
fail is to give your program a text file or apipe as the standard input instead of your terminal. To give it a file asstandard input, run ./kilo . To give it a pipe, run
echo test | ./kilo
. Both should result in the same error from tcgetattr()
,something like Inappropriate ioctl for device
.
Linux Termios
Sections
That just about concludes this chapter on entering raw mode. The last thingwe'll do now is split our code into sections. This will allow these diffs to beshorter, as each section that isn't changed in a diff will be folded into asingle line.
Step 19
atexit()
comes from . We use it to register our
disableRawMode()
function to be called automatically when the program exits,whether it exits by returning from main()
, or by calling the exit()
function. This way we can ensure we'll leave the terminal attributes the waywe found them when our program exits.
We store the original terminal attributes in a global variable, orig_termios
.We assign the orig_termios
struct to the raw
struct in order to make a copyof it before we start making our changes.
There's no catch! Play as much as you want, as long as you like! One of the most popular online action games of all time, Team Fortress 2 delivers constant updates—new game modes, maps, equipment and, most importantly, hats. TF2 Classic runs separate from your Team Fortress install. This means that usage of this software will not and cannot directly impact your Team Fortress 2 game or items. First of all you're going to need to fire up your fastest dial-up connection and click on the download. Click here to download the game.
You may notice that leftover input is no longer fed into your shell after theprogram quits. This is because of the TCSAFLUSH
option being passed totcsetattr()
when the program exits. As described earlier, it discards anyunread input before applying the changes to the terminal. (Note: This doesn'thappen in Cygwin for some reason, but it won't matter once we are reading inputone byte at a time.)
Turn off canonical mode
There is an ICANON
flag that allows us to turn off canonical mode. This meanswe will finally be reading input byte-by-byte, instead of line-by-line.
ICANON
comes from . Input flags (the ones in the
c_iflag
field) generally start with I
like ICANON
does. However, ICANON
is not aninput flag, it's a 'local' flag in the c_lflag
field. So that's confusing.
Now the program will quit as soon as you press q.
Display keypresses
To get a better idea of how input in raw mode works, let's print out each bytethat we read()
. We'll print each character's numeric ASCII value, as well asthe character it represents if it is a printable character.
iscntrl()
comes from , and
printf()
comes from .
iscntrl()
tests whether a character is a control character. Controlcharacters are nonprintable characters that we don't want to print to thescreen. ASCII codes 0–31 are all control characters, and 127 is also acontrol character. ASCII codes 32–126 are all printable. (Check out theASCII table to see all of the characters.)
printf()
can print multiple representations of a byte. %d
tells it toformat the byte as a decimal number (its ASCII code), and %c
tells it towrite out the byte directly, as a character.
This is a very useful program. It shows us how various keypresses translateinto the bytes we read. Most ordinary keys translate directly into thecharacters they represent. But try seeing what happens when you press the arrowkeys, or Escape, or Page Up, or Page Down, orHome, or End, or Backspace, orDelete, or Enter. Try key combinations withCtrl, like Ctrl-A, Ctrl-B, etc.
You'll notice a few interesting things:
- Arrow keys, Page Up, Page Down, Home, andEnd all input 3 or 4 bytes to the terminal:
27
,'['
, and thenone or two other characters. This is known as an escape sequence. Allescape sequences start with a27
byte. Pressing Escape sends asingle27
byte as input. - Backspace is byte
127
. Delete is a 4-byte escapesequence. - Enter is byte
10
, which is a newline character, also known as'n'
. - Ctrl-A is
1
, Ctrl-B is2
, Ctrl-C is…oh, that terminates the program, right. But the Ctrl keycombinations that do work seem to map the letters A–Z to the codes1–26.
By the way, if you happen to press Ctrl-S, you may find your programseems to be frozen. What you've done is you've asked your program to stopsending you output. PressCtrl-Q to tell it to resume sending you output.
Also, if you press Ctrl-Z (or maybe Ctrl-Y), your programwill be suspended to the background. Run the fg
command to bring it back tothe foreground. (It may quit immediately after you do that, as a result ofread()
returning -1
to indicate that an error occurred. This happens onmacOS, while Linux seems to be able to resume the read()
call properly.)
Turn off Ctrl-C and Ctrl-Z signals
By default, Ctrl-C sends a SIGINT
signal to the current processwhich causes it to terminate, and Ctrl-Z sends a SIGTSTP
signal tothe current process which causes it to suspend. Let's turn off the sending ofboth of these signals.
ISIG
comes from . Like
ICANON
, it starts with I
but isn't aninput flag.
Now Ctrl-C can be read as a 3
byte and Ctrl-Z can beread as a 26
byte.
This also disables Ctrl-Y on macOS, which is like Ctrl-Zexcept it waits for the program to read input before suspending it.
Disable Ctrl-S and Ctrl-Q
By default, Ctrl-S and Ctrl-Q are used forsoftware flow control.Ctrl-S stops data from being transmitted to the terminal until youpress Ctrl-Q. This originates in the days when you might want topause the transmission of data to let a device like a printer catch up. Let'sjust turn off that feature.
IXON
comes from . The
I
stands for 'input flag' (which it is,unlike the other I
flags we've seen so far) and XON
comes from the names ofthe two control characters that Ctrl-S and Ctrl-Qproduce: XOFF
to pause transmission and XON
to resume transmission.
Now Ctrl-S can be read as a 19
byte and Ctrl-Q can beread as a 17
byte.
Disable Ctrl-V
On some systems, when you type Ctrl-V, the terminal waits for you totype another character and then sends that character literally. For example,before we disabled Ctrl-C, you might've been able to typeCtrl-V and then Ctrl-C to input a 3
byte. We can turnoff this feature using the IEXTEN
flag.
Turning off IEXTEN
also fixes Ctrl-O in macOS, whose terminaldriver is otherwise set to discard that control character.
IEXTEN
comes from . It is another flag that starts with
I
butbelongs in the c_lflag
field.
Ctrl-V can now be read as a 22
byte, and Ctrl-O as a15
byte.
Fix Ctrl-M
If you run the program now and go through the whole alphabet while holding downCtrl, you should see that we have every letter except M.Ctrl-M is weird: it's being read as 10
, when we expect it to beread as 13
, since it is the 13th letter of the alphabet, andCtrl-J already produces a 10
. What else produces 10
? TheEnter key does.
It turns out that the terminal is helpfully translating any carriage returns(13
, 'r'
) inputted by the user into newlines (10
, 'n'
). Let's turnoff this feature.
ICRNL
comes from . The
I
stands for 'input flag', CR
standsfor 'carriage return', and NL
stands for 'new line'.
Now Ctrl-M is read as a 13
(carriage return), and theEnter key is also read as a 13
.
Turn off all output processing
It turns out that the terminal does a similar translation on the output side.It translates each newline ('n'
) we print into a carriage return followed bya newline ('rn'
). The terminal requires both of these characters in orderto start a new line of text. The carriage return moves the cursor back to thebeginning of the current line, and the newline moves the cursor down a line,scrolling the screen if necessary. (These two distinct operations originated inthe days of typewriters andteletypes.)
We will turn off all output processing features by turning off the OPOST
flag. In practice, the 'n'
to 'rn'
translation is likely the only outputprocessing feature turned on by default.
OPOST
comes from .
O
means it's an output flag, and I assumePOST
stands for 'post-processing of output'.
If you run the program now, you'll see that the newline characters we'reprinting are only moving the cursor down, and not to the left side of thescreen. To fix that, let's add carriage returns to our printf()
statements.
Termios.h Mingw
From now on, we'll have to write out the full 'rn'
whenever we wantto start a new line.
Miscellaneous flags
Let's turn off a few more flags.
BRKINT
, INPCK
, ISTRIP
, and CS8
all come from .
This step probably won't have any observable effect for you, because theseflags are either already turned off, or they don't really apply to modernterminal emulators. But at one time or another, switching them off wasconsidered (by someone) to be part of enabling 'raw mode', so we carry on thetradition (of whoever that someone was) in our program.
As far as I can tell:
- When
BRKINT
is turned on, abreak condition willcause aSIGINT
signal to be sent to the program, like pressingCtrl-C
. INPCK
enables parity checking, which doesn't seem to apply to modernterminal emulators.ISTRIP
causes the 8th bit of each input byte to be stripped, meaning itwill set it to0
. This is probably already turned off.CS8
is not a flag, it is a bit mask with multiple bits, which we set usingthe bitwise-OR (|
) operator unlike all the flags we are turning off. Itsets the character size (CS) to 8 bits per byte. On my system, it's alreadyset that way.
A timeout for read()
Currently, read()
will wait indefinitely for input from the keyboard beforeit returns. What if we want to do something like animate something on thescreen while waiting for user input? We can set a timeout, so that read()
returns if it doesn't get any input for a certain amount of time.
VMIN
and VTIME
come from . They are indexes into the
c_cc
field, which stands for 'control characters', an array of bytes that controlvarious terminal settings.
The VMIN
value sets the minimum number of bytes of input needed beforeread()
can return. We set it to 0
so that read()
returns as soon as thereis any input to be read. The VTIME
value sets the maximum amount of time towait before read()
returns. It is in tenths of a second, so we set it to 1/10of a second, or 100 milliseconds. If read()
times out, it will return 0
,which makes sense because its usual return value is the number of bytes read.
When you run the program, you can see how often read()
times out. If youdon't supply any input, read()
returns without setting the c
variable,which retains its 0
value and so you see 0
s getting printed out. If youtype really fast, you can see that read()
returns right away after eachkeypress, so it's not like you can only read one keypress every tenth of asecond.
If you're using Bash on Windows, you may see that read()
still blocks forinput. It doesn't seem to care about the VTIME
value. Fortunately, this won'tmake too big a difference in our text editor, as we'll be basically blockingfor input anyways.
Error handling
enableRawMode()
now gets us fully into raw mode. It's time to clean up thecode by adding some error handling.
First, we'll add a die()
function that prints an error message and exits theprogram.
perror()
comes from , and
exit()
comes from .
Include Termios H R
Most C library functions that fail will set the global errno
variable toindicate what the error was. perror()
looks at the global errno
variableand prints a descriptive error message for it. It also prints the string givento it before it prints the error message, which is meant to provide contextabout what part of your code caused the error.
After printing out the error message, we exit the program with an exit statusof 1
, which indicates failure (as would any non-zero value).
Let's check each of our library calls for failure, and call die()
when theyfail.
#include Sys/termios.h
errno
and EAGAIN
come from .
tcsetattr()
, tcgetattr()
, and read()
all return -1
on failure, and setthe errno
value to indicate the error.
In Cygwin, when read()
times out it returns -1
with an errno
of EAGAIN
,instead of just returning 0
like it's supposed to. To make it work in Cygwin,we won't treat EAGAIN
as an error.
An easy way to make tcgetattr()
fail is to give your program a text file or apipe as the standard input instead of your terminal. To give it a file asstandard input, run ./kilo . To give it a pipe, run
echo test | ./kilo
. Both should result in the same error from tcgetattr()
,something like Inappropriate ioctl for device
.
Linux Termios
Sections
That just about concludes this chapter on entering raw mode. The last thingwe'll do now is split our code into sections. This will allow these diffs to beshorter, as each section that isn't changed in a diff will be folded into asingle line.
Step 19
Include Termios H T
In the next chapter, we'll do some more low-levelterminal input/output handling, and use that to draw to the screen and allowthe user to move the cursor around.