隐藏 ^c在C中按Ctrl-c



我正在创建自己的外壳,当任何linux发行版上的任何用户按 ctrl c

我不需要处理信号sigint,我已经这样做了,因为不要在 ctrl ctrl上停止程序。我只想知道如何隐藏这些两个字符 ^c

在我的程序开始时是否有任何函数要调用或ENV变量?

编辑

  int a = fork();
  if (!a) {
    char *cmd[] = {"/bin/stty", 0 };
    char *cmd_args[] = {" ", "-echoctl", 0};
    execve(cmd[0], cmd_args, env);
  }

尝试了这个。它在Ctrl-C上删除了我的 ^c,但仍然显示一个正方形字符,就像无法显示字符一样。它似乎是EOT(003 ASCII)

^C来自Linux

中的终端驱动程序的回声

这是C中的一个示例程序。它首先会保存当前设置,并在程序退出时注册atexit处理程序以还原设置,然后在标准输入终端上禁用Echo。然后,它在循环时进入无限。现在,当您在终端上键入任何内容时, nothing 都会显示出任何^C

外壳使用的技巧是它们 在终端上的输入处理,关闭规范输入处理,并一次读取标准输入一个字符,然后在其上处理回声自己的 - 需要代码远远超过堆栈溢出答案的东西。

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

struct termios saved;
void restore(void) {
    tcsetattr(STDIN_FILENO, TCSANOW, &saved);
}

int main() {
    struct termios attributes;
    tcgetattr(STDIN_FILENO, &saved);
    atexit(restore);
    tcgetattr(STDIN_FILENO, &attributes);
    attributes.c_lflag &= ~ ECHO;
    tcsetattr(STDIN_FILENO, TCSAFLUSH, &attributes);
    printf("Entering the loopn");
    while(1) {};
}

运行stty -echoctl应该隐藏它。有关更多详细信息,请参见man stty

您可以使用ANSI逃生代码删除 ^C字符。在处理Sigint信号的功能中,打印向左两次移动光标的字符,然后删除右侧的所有字符至行末端。

下面的示例可在MacOS和Raspberry Pi OS上使用。

在Windows上不需要此技巧,因为按Ctrl C是无声的。

/**
    remove_ctrl_c.c
    gcc remove_ctrl_c.c -o remove_ctrl_c && ./remove_ctrl_c
    Remove the characters ^C with ANSI escape codes.
    (see https://en.wikipedia.org/wiki/ANSI_escape_code)
    b     : Move cursor one character on the left.
    b     : Idem
    33[K : Delete all the characters on the right of
             the cursor until the end of the line.
             You can also use two spaces if you prefer,
             but they will be present in the output although
             they are not visible.
    n     : Add a new line. This is optional,
             but if you remove it and some characters
             are printed on the last line, the terminal
             will add an extra % character to indicate
             that the new line character was absent.
    Note that, as the printf command is buffered,
    we need to use the fflush command before the end
    of the program to force stdout to be updated.
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
volatile sig_atomic_t KEYBOARD_INTERRUPT = 0;
void handleSignal(int signal)
{
    KEYBOARD_INTERRUPT = 1;
}
int main()
{
    signal(SIGINT, handleSignal);
    printf("Remove ^C on exit!");
    fflush(stdout);
    while (!KEYBOARD_INTERRUPT)
    {
    }
    printf("bb33[Kn");
    fflush(stdout);
    return 0;
}

最新更新