I have implemented my own shell which executes all existing UNIX commands and several custom commands. What I need to do is, to access previous commands by using arrow up/down keys in the way exactly how UNIX terminal does.
I have found that I could use getch() method of <curses.h> library. Even if I couldn't figure out how to use that method to expect non-blocking keyboard input, the real problem with that is that I need to compile the program to be able use it as following: gcc myShell.c -lcurses
What I have to do is probably using a signal to listen background input without expecting Enter input. I have also tried to fork() to create another process which will be responsible of waiting arrow keys inputs and then used getch() method to be able to catch the key but it didn't work either.
Since I already use read() method to read the command line inserted by the user. This arrow key input should be completely independent from the existing input reading.
Some answers in Stackoverflow points the <conio.h> library which does not exist in UNIX, hence unfortunately platform dependent.
To summarize briefly, I need to read arrow up/down keys in the background in my own shell and I have to do that platform independent and without being have to type something other than gcc myShell.c for compilation. It also should be captured without Enter press.
If any details about my question is not clear enough, please let me know to explain with more details as I could.
Thanks in advance!
The problem here is with the terminal you're using, not your program. For example, Windows command prompt will buffer input before even sending it to your program, so there is no platform-independent way to force the terminal to give you that data. I suspect curses has a platform-dependent way to turn off that buffering, and thus can get the character.
See answers to this question for more details: How to avoid press enter with any getchar()
Related
This is what says on http://invisible-island.net/ncurses/ncurses.faq.html#multithread
If you have a program which uses curses in more than one thread, you will almost certainly see odd behavior. That is because curses relies upon static variables for both input and output. Using one thread for input and other(s) for output cannot solve the problem, nor can extra screen updates help. This FAQ is not a tutorial on threaded programming.
Specifically, it mentions it is not safe even if input and output are done on separate threads. Would it be safe if we further use a mutex for the whole ncurses library so that at most one thread can be calling any ncurses function at a time? If not, what would be other cheap workarounds to use ncurses safely in multi-thread application?
I'm asking this question because I notice a real application often has its own event loop but relies on ncurses getch function to get keyboard input. But if the main thread is block waiting in its own event loop, then it has no chance to call getch. A seemingly applicable solution is to call getch in a different thread, which hasn't caused me a problem yet, but as what says above is actually not safe, and was verified by another user here. So I'm wondering what is the best way to merge getch into an application's own event loop.
I'm considering making getch non-blocking and waking up the main thread regularly (every 10-100 ms) to check if there is something to read. But this adds an additional delay between key events and makes the application less responsive. Also, I'm not sure if that would cause any problems with some ncurses internal delay such as ESCDELAY.
Another solution I'm considering is to poll stdin directly. But I guess ncurses should also be doing something like that and reading the same stream from two different places looks bad.
The text also mentions the "ncursest" or "ncursestw" libraries, but they seem to be less available, for example, if you are using a different language binding of curses. It would be great if there is a viable solution with the standard ncurses library.
Without the thread-support, you're out of luck for using curses functions in more than one thread. That's because most of the curses calls use static or global data. The getch function for instance calls refresh which can update the whole screen—using the global pointers curscr and stdscr. The difference in the thread-support configuration is that global values are converted to functions and mutex's added.
If you want to read stdin from a different thread and run curses in one thread, you probably can make that work by checking the file descriptor (i.e., 0) for pending activity and alerting the thread which runs curses to tell it to read data.
I'm trying to exit the console screen i.e close the screen what command can i use to achieve this.
void main()
{
int n;
printf("Please enter a number less than 5");
scanf("%d", &n);
if(n <= 5)
printf("good");
else
{
printf("You entered a number above so the program will exit");
//here i need to call a function or use a command that will close
// the console screen;
}
}
Any help will be appreciated thanks
The C11 standard n1570 does not know about the "console screen" (and I guess you speak of the terminal emulator running your program). Notice that C11 does not mention "screens" or "keyboards" (only standard streams, and very often stdout is not a "console") and many computers (e.g. most Internet servers or supercomputers, or even your mobile phone...) don't have both. Also, your program could be run (even on Windows) with redirections or in a pipeline and then it has no console (so your question don't make any sense in such a common case).
So in general, there is no way to do what you want (since it does not make any sense), in a standard way.
Perhaps your operating system provide some (OS specific) way to achieve that. So investigate the OS API relevant to your system (e.g. WinAPI on Windows, or Linux syscalls -listed in syscalls(2)).
Perhaps you want to use some terminal related library like ncurses.
If your terminal follows the ANSI escape code conventions, you might follow them.
Otherwise, consider making your program having some GUI. For that, you practically need some widget toolkit (such as Qt, GTK, etc..)
You might also consider some inter-process communication with your desktop environment. How to do that (or even its possibility) is very operating-system and desktop specific and might be related to session management.
BTW, remember that stdout is often buffered (and perhaps line-buffered). You'll better end your printf control strings with \n and/or call fflush.
In a windowing operating system or execution environment the console window will close immediately the process terminates, so it is not clear what you are asking here since in your example the program terminates regardless of what input is entered.
If you are running the code from an IDE, often the IDE will create a console process and launch your code within that. In that case the console is not "owned" by your application, but is executed as a child process; in which case the window will remain open until the parent process launched by the IDE is closed. Similarly if you launch your program from a command shell. It is probably unreasonable behaviour for a process to attempt to close its parent even if it is possible.
It is possible to "hide" the console window while the process continues to run, which may be what you are asking; the means of doing that is platform specific, and you have not specified; for Windows such a question would be a duplicate of Win32 programming hiding console window. However it is quite possible that these methods will not work if the process is not launched directly but from some other console process.
in Windows you may simply write code on Notepad, then compile and run it through the Command prompt (cmd.exe). If you have GCC installed as compiler (with all the needed packages), then compile your main.c file as:
gcc main.c -o main.exe
If all went fine, as you run "main", there will be all of your output that you can close or step over for more editing. Bye
PS EDIT -- I see your point: when you launch your .exe from itself, the window closes without giving satisfaction of the messages. You may add a workaround like this before the last curly bracket:
printf("Press any key\n");
scanf("%d");
}
So the output window will still wait for one more input before closing.
You may check for additional information for eg here: https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html
Bye
I am writing a program which has a main menu, with a couple functions which I am allowing the user to access by typing in a number for one menu selections. For that, I am using _getch(). I need to be able to exit the program when the user enters the EOF key, but _getch() does not actually catch the EOF keystroke. I know I can get it to work by using getchar() instead of _getch(), but I would prefer not to have the user be forced to press enter after every function selection.
Is there a way to get _getch() to catch EOF? This is for Windows if it is of any importance, any help is really appreciated, as I have been unable to find anything out there.
The standard C input stream stdio is line buffered, and there is no defined way to forcibly flush it. If you want to avoid this and read from the buffer as every new character is entered, you have to use some OS specific magic, which is what _getch from conio.h tries to do.
There are other implementations out there of getch-type functions, for instance getch from the PDCurses library.
I am trying to implement a simple shell in linux and one of the features it should have is to enable to user to press <ctrl+D> and make it stop whatever it is doing - Basicly exactly what <ctrl+C> does in Bash.
Now I was wondering on the easiest way to do this, and I was thinking of some kind of key listener which would make the current task stop. Now the only way I could think of doing this would be to have a separate thread which would force stop and return the main thread to the base state, where it can take new input.
A separate thread would be the only way to "constantly" listen for the correct keypress.
I was hoping for some thoughts on this and possibly a better way to go about it.
[Edit]
I am trying to make a simple shell which can execute external programs, print/change directory, print/set path, print command history, invoke commands from history and print/set/remove command aliases. The CTRL-D is meant to be the equivalent of the CTRL-C in Bash, which allows the user to immediately exit a currently running program, not to exit the shell itself. [/Edit]
Why don't you just handle Ctrl-C?
Here is just one of many SO disussions on trapping the signal: Catch Ctrl-C in C
Ctrl-D generally represents EOF on standard input. You shouldn't mess with it.
If you want the Control-D character to generate an interrupt for you, then:
You need to map the EOF character to something other than Control-D.
You need to map the interrupt character to Control-D.
You do this in POSIX with the <termios.h> header and the functions:
tcgetattr()
tcsetattr()
You'd retrieve the current attributes in a struct termios using tcgetattr(). You'd make a copy of the structure, and modify (for sake of argument) the copy, changing the elements of the c_cc array indexed by VINTR and VEOF (plus any other changes you want to make), and then setting the new attributes using tcsetattr(). You'd also arrange to ensure that you restore the original terminal settings (by another call to tcsetattr() using the original set of attributes retrieved with tcgetattr()) before your shell exits. This might be done by a handler registered with atexit(), or by other mechanisms. You should endeavour to reset the terminal attributes under all circumstances. You can't do anything about a SIGKILL killing you.
While you're testing this, make a little script for yourself:
echo stty $(stty -g) > sane
chmod u+x sane
That records the current (presumably sane) terminal settings in a form that is designed for stty to read reliably. If (when) you have problems with your shell, you can use Control-JsaneControl-J to run the script and reset your terminal back to the known sane settings. This is also useful if you're developing programs that use the curses library.
Unless my comment on the other answer is incorrect, I think what you should do is:
if (!fgets(input, sizeof(input), stdin) == NULL)
{
... do cleanup here ...
exit(0);
}
or something equivalent to that.
How can I execute a command when user press a key in a command-line C application? Is it possible when window isn't focused
Depends on the program itself, you could do either of those:
block on unbuffered getc you get the key strokes as they come and not when users hits return.
create some sort of event loop, using select/epoll or event framework like (libevent/libev) and get a callback whenever a user hits a key.
use a toolkit like ncurses which provides a pseudo graphical command line interface and an event loop.
if the keys you're interesting in capturing are things like CTRL+C, you need signal handlers.