【问题标题】:Exit read listening when pressing "Ctrl + c" in C在 C 中按“Ctrl + c”时退出读取侦听
【发布时间】:2017-03-22 18:50:27
【问题描述】:

我正在用 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] = '\0';
return (strdup(command));

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

感谢您的帮助!

【问题讨论】:

  • man siglongjmp
  • 感谢您的回复,但是是学校项目,这个功能是不允许的。
  • 不清楚您的问题是什么,因为您没有显示任何代码或讨论您是否在 shell 中操作信号处理或终端设置。您可能会发现 Canonical vs non-canonical terminal input 很有帮助,或者它可能是一个红鲱鱼。您应该讨论(更好地,展示)您的外壳如何处理信号。 Control-C 应该生成一个 SIGINT;如果你的 shell 忽略了这一点,或者处理不当,它可能会导致你的麻烦。
  • 好吧,从技术上讲,它不是一个函数,虽然它看起来是。
  • 我编辑了我的问题。 (Ctrl + d 效果很好)

标签: c stdout stdin ctrl


【解决方案1】:

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

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

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

您需要在信号处理程序中处理^C,并适当调整您的shell 的状态,使其放弃当前输入模式并重新绘制基本提示。


编辑:您需要记住的是,您的“外壳”正在向终端仿真器写入文本(输出)和控制字符 - 终端仿真器正在向终端仿真器写入文本(输入)和控制字符你的“外壳”。

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

要跟踪您当前正在做什么,使用State Machine 方法可能最有意义。您可能有几个州,包括:

  1. INPUT_WAITING
  2. INPUT_WAITING_CONT
  3. COMMAND_RUN

当处于INPUT_WAITING 状态时,您将打印mysh$ 提示并处理输入。 收到换行符后,您将决定“我们是否拥有所有信息?”如果没有,则进入 INPUT_WAITING_CONT 状态,如果有,则进入 COMMAND_RUN 状态。 p>

INPUT_WAIT_CONT 状态将打印出dquote> 提示,并采取类似的操作... '我们有足够的信息吗?' 是:COMMAND_RUN,否:INPUT_WAIT_CONT

然后,当用户按下^C 或命令执行完成时,您可以恢复到INPUT_WAIT 状态并重新绘制mysh$ 提示符。

【讨论】:

  • 对不起,我混淆了 EOF 和 EOT。 Ctrl + d 发送由read 函数读取的EOT。所以我在想如果我能写一个 EOT,read 会读它,我可以像^C 一样正确对待它。 “放弃当前输入”如何?那是我的问题。
  • Ctrl + d send a EOT which is read by read function 不在 UNIX 上。通常,^D 由终端驱动程序处理(并转换为 EOF event),读取程序永远不会看到 0x04。
猜你喜欢
  • 2020-10-11
  • 1970-01-01
  • 1970-01-01
  • 2018-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多