1

I am creating a little shell which executes linux bash commands in ubuntu with fork and exec commands. I need to bring previous commands when up button is clicked and need to bring next command when down button is clicked as same as terminal. How can I do this with native C language?

I mean I need to scan all the time like a listener in object oriented for up and down buttons.

JollyRoger
  • 737
  • 1
  • 12
  • 38
  • Possible duplicate of [getch and arrow codes](https://stackoverflow.com/questions/10463201/getch-and-arrow-codes) – yakout Nov 03 '17 at 19:49
  • You need to modify the terminal connected to your shell to give you such key-sequences. That's usually done with the help of [*termcap* (terminal capabilites)](http://man7.org/linux/man-pages/man5/termcap.5.html). If you search for the term `termcap` you should be able to find plenty of example on how to use it. With its help the terminal will send such keys such as cursor up or down as special sequences to your application, which you can detect when reading, and handle as appropriate. – Some programmer dude Nov 03 '17 at 19:49
  • @yakout I think this is asking how to implement the UI and callback to read the button messages. – Cpp plus 1 Nov 03 '17 at 19:50
  • Or, you know, use a library such as [the GNU readline library](https://en.wikipedia.org/wiki/GNU_Readline) (which exists on all major Linux distributions) and which will help you with all these things (the library even have its own built-in history functionality, which seems to be what you're after). – Some programmer dude Nov 03 '17 at 19:51
  • Thanks for all responses. I think I found more than 1 way to do this in these comments, thanks. – JollyRoger Nov 03 '17 at 19:56

1 Answers1

0

If it's a small project for educational purpose you can try to look at tcgetattr (man page is very descriptive).

This is an example of proper configuration:

#include <termios.h>
#include <unistd.h>

struct termios old_term;

void set_new_term() {
  struct termios new_term;

  tcgetattr(STDIN_FILENO, &old_term);
  tcgetattr(STDIN_FILENO, &new_term);

  new_term.c_lflag &= (~ICANON & ~ECHO);
  new_term.c_cc[VMIN] = 0;
  new_term.c_cc[VTIME] = 0;
  tcsetattr(STDIN_FILENO, TCSAFLUSH, &new_term);
}

And don't forget to restore old terminal settings before exit (with tcsetattr(STDIN_FILENO, TCSANOW, &old_term))

So the idea is to set noncanonical mode.

In noncanonical mode input is available immediately (without the user having to type a line-delimiter character), no input processing is performed, and line editing is disabled.

And now, when you're done with terminal, you need to track all strings of the form

str[0] = '\x1b'
str[1] = '['
str[2] = 'A' or 'B' or 'C' or 'D' /* A - for up
                                     B - down
                                     C - right
                                     D - left  */

But once again all this is useful only if you want to have fun, but in general I think readline is a good solution. There is even rlwrap available on ubuntu.

rlwrap runs the specified command, intercepting user input in order to provide readline's line editing, persistent history and completion.

So you can run:

$> rlwrap your_program_name
vonaka
  • 913
  • 1
  • 11
  • 23
  • Thanks for the reply. I did not tryed this but I am sure it will work. Actually I solved my problem with an easier way. Using getch( ) as it described in here https://stackoverflow.com/questions/10463201/getch-and-arrow-codes . – JollyRoger Nov 04 '17 at 19:37