在 C 中按 "Ctrl + c" 退出阅读监听

Exit read listening when pressing "Ctrl + c" in C

我正在用 C 语言重写一个 shell,我遇到了一个问题。

写命令时——例如 echo "this——我们得到一个新提示("dquote>",在 zsh 中),我们可以使用 "Ctrl + c" 退出它并返回到我们的上一个命令提示符。

我被困在那里;我只是无法退出我的读取功能(在 "dquote>" 上监听),我试图在按下 "ctrl + c" 时在标准输出上写一个 EOF 但它没有读取它。

我切换到非规范模式。 我用 signal(SIGINT, sig_hand);

捕捉信号

然后我在捕捉到信号时执行这部分代码:

static void sig_hand(int sig)
{
    if (g_shell.is_listen_bracket) // if is the first prompt or no
        putchar(4); // EOT
    else
    {
        putstr("\n");
        print_prompt();
    }
}

和我的阅读功能:

int     j;
char    command[ARG_MAX];
char    buff[3];

j = -1;
while (1)
{
    bzero(buff, 3);
    read(0, buff, 3);
    if (buff[0] == 4 && !buff[1] && !buff[2])
        return (ctrl_d(shell));
    else if (isprint(buff[0]) && !buff[1] && !buff[2]) // if is between 32 and 126 (ascii)
    {
        command[++j] = buff[0];
        putchar(buff[0]);
    }
}
command[++j] = '[=12=]';
return (strdup(command));

所以我的代码在等待 "read(0, buff, 3);",我想在按 ctrl + c 时退出它。

感谢您的帮助!

不要把EOF当成一个可以'打印到stdout'的字符,它是文件句柄可以的状态在,这意味着没有更多的数据到来。要将 stdout 置于 EOF 状态,您必须调用 close() - 这很可能不是您想要的。

注意 - 0x04 实际上是 EOT,传输结束。

无论如何,为什么要将 EOT 发送到应用程序的 stdout?如果这表现得像你认为的那样,那么终端仿真器(或连接到你的标准输出的任何东西)将退出 - 而不是你的 shell,它肯定不会恢复你的 shell从“等待更多输入”状态到“等待输入”状态。

你需要在signal handler中处理^C,适当调整你的shell状态,让它放弃当前的输入模式,重绘基本提示。


编辑: 您需要记住的是,您的 'shell' 正在向终端仿真器写入文本(输出)和控制字符 - 终端仿真器正在写入文本(输入)和控制字符到您的 'shell'.

如果您想将提示从 dquote> 还原为 mysh$,那么 必须通过向终端写入新提示来更新终端。

要跟踪您当前正在做的事情,使用 State Machine 方法可能最有意义。您可能有几个状态,包括:

  1. INPUT_WAITING
  2. INPUT_WAITING_CONT
  3. COMMAND_RUN

当处于 INPUT_WAITING 状态时,您将打印 mysh$ 提示,并处理输入。 当收到换行符时,您将决定“我们是否拥有所有信息?”,如果没有则进入 INPUT_WAITING_CONT 状态,或者 COMMAND_RUN如果你这样做,请说明。

INPUT_WAIT_CONT 状态将打印出 dquote> 提示,并采取类似的操作... 'do we have enough information?' 是:COMMAND_RUN,否:INPUT_WAIT_CONT.

然后由您恢复到 INPUT_WAIT 状态并在用户按下 ^C 或命令执行完成时重绘 mysh$ 提示。