处理linux上的用户输入

时间:2015-12-26 21:40:48

标签: c linux input

我正在努力在linux上创建一个简单的shell。我可以创建一些东西来学习如何使用基本系统调用。

方案: 命令中的用户类型,按Tab键(因此shell自动完成其命令),弹出自动完成的命令(或建议),用户按Enter键,命令evals并执行。

就像在bash中一样。

我已经想出了如何进行篡改,将命令转换为令牌,使用管道和东西执行它。我无法弄清楚的是输入部分。即那些标签击键。

我知道我有什么选择:

  • getc() - 分别获取每个字符,将其存储在缓冲区中。无法弄清楚如何获得标签击键,因为它会暂停执行,直到它看到' \ n'或Ctrl + D.有点贵,因为命令中的每个字符都会有1个getc()。另外,我将不得不处理缓冲区重新分配,摊销......嘘......
  • scanf("%s") - 太担心缓冲区溢出。无法获得我不想要的那些标签击键。暂停执行
  • read()(来自unistd.h) - 可能是我不想要的。但我在这里看到的人说,用它来做这件事真的很痛苦。我检查了。它是。
  • getline() - 无法获得标签击键。

我研究了bash源代码,看看它是如何处理输入的,以及OH MY GOD。有450行代码专门用来做这个简单的事情(input.c文件)。

真的没有比这更简单的解决方案吗?我不想使用ncurses,我不关心可移植性,我只是想实现一个目标:获取用户输入并知道何时按Tab键。尽可能少地努力做到优雅。

2 个答案:

答案 0 :(得分:4)

为了在没有任何延迟或缓冲的情况下从终端获得单独的击键,您必须将其模式从cooked更改为raw。您可以使用tcsetattr()中定义的<termios.h>函数执行此操作。有关详细信息,请查看手册页。

将终端设置为适当的模式后,最好使用read()系统调用从终端句柄读取数据。

请注意,您必须处理回显用户输入,如果您开始执行TAB扩展等高级内容,则需要实现大多数行编辑器...更不用说处理字符组成和其他奇怪的终端给你免费的。正如Basile所说,没有简单的手工解决方案,但潜入这个混乱将是非常有益的!

如果您需要时间并且这是一个受让人,请使用readline()并首先实现shell的其余部分。这将是很多工作。如果你还敢,你可以随时回到这里。

答案 1 :(得分:4)

要获得某些特定的自动完成功能,您可以使用bash使用的GNU readline库。

如果您关心终端全屏I / O(例如viemacs),请考虑GNU ncurses

终端是相当复杂和神秘的东西(因为他们想模仿上个世纪奇怪的物理电传类型)。通常,一些行处理是在内核中为tty的line discipline完成的。阅读tty demystified网页。因此,la termios(3)的低级别功能使用起来很神秘,您应该更喜欢readlinencurses等库。

所以,不,没有用于自动完成的终端I / O的简单解决方案,因为ttys是复杂的东西。另见tty(4)&amp; tty_ioctl(4)&amp; pty(7)

您还可以使用strace(1)来理解所有复杂的system calls。一个互动的外壳。

另见this&amp; that回答。