readchar.cc
// readchar.cc
/* Sample code to read from the console a character at a time.
*
* CS-701
* Spring 2003
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
static struct termios saved, raw;
// restoreTTY()
// ------------------------------------------------------------------
void
restoreTTY( void )
{
tcsetattr( STDIN_FILENO, 0, &saved );
exit( 0 );
}
// main()
// ------------------------------------------------------------------
int
main(int argc, char*argv[], char*envp[])
{
// Make sure it makes sense to process input a char at a time.
const char notATTY[] = "Stdin is not a terminal\n";
if ( 0 == isatty( 0 ) )
{
write( 1, notATTY, strlen( notATTY ) );
exit( 1 );
}
// Save original tty state, and set up to restore it at exit.
if ( -1 == tcgetattr( STDIN_FILENO, &saved ) )
{
perror( "Unable to save tty attributes" );
exit( 1 );
}
if ( -1 == atexit( restoreTTY ) )
{
perror( "Unable to intercept exit calls" );
exit( 1 );
}
// Put tty into raw mode
raw = saved;
raw.c_lflag &= ~ICANON & ~ECHO;
raw.c_cc[ VMIN ] = 1;
raw.c_cc[ VTIME ] = 0;
tcsetattr( STDIN_FILENO, 0, &raw );
const char prompt[] = "jsh> ";
const char crlf[] = "\r\n";
char aChar;
char inBuf[ 10 ];
bool endline = false;
for ( ;; )
{
endline = false;
memset( inBuf, '\0', sizeof( inBuf ) );
write( STDOUT_FILENO, prompt, strlen( prompt) );
for (unsigned int i = 0; i < (sizeof( inBuf ) - 2); i++ )
{
int numRead = read( STDIN_FILENO, &aChar, 1 );
if ( numRead < 1 )
{
perror( "\n\rError Reading" );
exit( 1 );
}
// Examples of things you can do in raw mode.
switch (aChar )
{
case '\x004':
// Control-D
write( STDOUT_FILENO, "^D", 2 );
if ( 0 == i )
{
// EOF
write( STDOUT_FILENO, crlf, sizeof( crlf ) );
exit( 0 );
}
endline = true;
break;
case '\n':
// Newline
write( STDOUT_FILENO, "^J", 2 );
endline = true;
break;
default:
inBuf[i] = aChar;
}
if ( endline )
{
break;
}
write( STDOUT_FILENO, &aChar, 1 );
}
printf( "\nYou typed \"%s\"\n", inBuf );
}
}