Work with user input on Linux

I am struggling to create a simple linux shell. I can simply create to learn how to use basic system calls.

Scenario : the user types in a command clicks a tab (so that the shell automatically completes its command), the autocomplete command issues (or sentences), enters a user click, the evals command and executes.

As in bash.

I figured out how to make assessments, convert the team to tokens, execute it using pipes, etc. What I cannot understand is the input part. Namely, these keystrokes.

I know what my options are:

  • getc() - get each character separately, save it in the buffer. It is impossible to figure out how to get keystrokes, because it pauses until it sees "\ n" or Ctrl + D. Kinda is expensive, as there will be 1 getc () for each character in the command. Also, I have to deal with buffer reallocation, amortization ... boo ...
  • scanf("%s") - worries too much about buffer overflows. I can not get these keystrokes, which I did not. Pauses execution
  • read() (from unistd.h) - maybe something I don’t want. But I saw people here who said that it was a real pain to use it for this. I checked. It.
  • getline() - unable to get keystrokes.

I looked at the bash source code to see how it works with input, and OH MY GOD. There are 450 lines of code dedicated to this simple thing (input.c file).

Are there really no simpler solutions than this? I do not want to use ncurses, I do not care about portability, I just do not want to achieve one goal: to receive user input and knowing when he pressed the tab key. Do it elegantly with minimal effort.

+5
source share
2 answers

To get a specific auto-complete, you can use the GNU readline library, which is used by bash .

If you need full terminal I / O (à la vi or emacs ), consider GNU ncurses .

Terminals are quite complex and mysterious things (because they want to imitate the strange physical teletypes of the last century). Often part of the string processing is done in the kernel for the linear tty discipline . Read the tty demystified web page. Consequently, the low level à la termios (3) functions are secret to use, and you should prefer libraries like readline or ncurses .

So no, there are no easy solutions for terminal I / O to autocomplete, since ttys are complex. See also tty (4) and tty_ioctl (4) and pty (7)

You can also use strace (1) to understand the whole complex of system calls made, for example, by an interactive shell.

See also this one and which one answers.

+4
source

To receive individual keystrokes from the terminal without any delay or buffering, you must change its mode from cooked to unprocessed. You can do this with the tcsetattr() function defined in <termios.h> . See the man page for details.

After you set the terminal to the appropriate mode, it is reasonable to use the read() system call to read data from the terminal descriptor.

Keep in mind that you will have to deal with the echo of user data input, and if you start doing advanced things, such as the TAB extension, you will need to implement most of the linear editor ... Not to mention the processing of character composition and other oddities, the terminal gives you free. According to Bazile, there is no simple manual solution for this, but it is very instructive to plunge into this mess!

If you clicked on a time, and that is the assigned object, just use readline() and first implement the rest of the shell. It will already be a lot of work. You can always come back to this later if you still decide.

+4
source

Source: https://habr.com/ru/post/1239267/


All Articles