简体   繁体   English

与原始外壳一样处理Ctrl + C

[英]Handling Ctrl + C as in original shell

I'm trying to implement small shell program in C which will read commands from stdin, parse them and execute. 我正在尝试用C实现小型shell程序,该程序将从stdin读取命令,解析它们并执行。 I faced with problem of handling Ctrl+C as in original shell - when you type several letters, or doesn't type anything, and then press Cntrl+C, shell just returns new prompt back: 我遇到了在原始Shell中处理Ctrl + C的问题-当您键入多个字母或不键入任何内容,然后按Cntrl + C时,Shell只会返回新的提示:

user@user-pc:/$ some letters^C
user@user-pc:/$ 

Here is a simplified code to show my approach of doing that: 这是一个简化的代码,显示了我这样做的方法:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

char        interruption;

void        read_line(char **str)
{
    char    c;
    int     size;
    int     i;

    c = 0;
    size = 30;
    i = -1;
    *str = (char*)malloc(sizeof(char) * size + 1);
    while (c != '\n' && !interruption)
    {
        i++;
        if (i == size)
            *str = realloc((void*)*str, (size_t)((size *= 2) + 1));
        read(0, &c, 1);
        (*str)[i] = c;
    }
    if (interruption)
    {
        free(*str);
        *str = NULL;
        interruption = 0;
    }
    else
        (*str)[i] = '\0';
}

void        handler(int sig_num)
{
    (void)sig_num;
    signal(SIGINT, handler);
    interruption = 1;
    printf("\ninterruption happened\n");
}

int         main()
{
    char    *str;

    signal(SIGINT, handler);
    interruption = 0;
    while (1)
    {
        str = NULL;
        write(1, "%> ", 3);
        read_line(&str);
        if (str)
            printf("parsing %s\n", str);
        else
            printf("skipping...\n");
    }
    return (0);
}

The problem in my approach is that after pressing Ctrl+C prompt does not return, because read() starts actually reading from input only when I press Enter. 我的方法的问题在于,按Ctrl + C提示符后不会返回,因为read()实际上仅在按Enter时才开始从输入读取。 It is my school assignment and I can't use any functions except read() to read characters from stdin. 这是我的学校作业,除read()之外,我无法使用任何功能从stdin中读取字符。

What is the right way to reproduce the behavior of shell in this case? 在这种情况下,重现shell行为的正确方法是什么?

First of all... NEVER, EVER use printf or any other functions that are not guaranteed to be async-signal-safe inside a signal handler. 首先... 永远不要在信号处理程序中使用printf或任何其他不能保证异步信号安全的函数。

Really. 真。 Just don't. 只是不要。

Secondly, use sigaction function instead of signal function to install your signal handler, just like that. 其次,使用sigaction函数而不是signal函数来安装信号处理程序,就像这样。 So here's the code for signal handler: 因此,这是信号处理程序的代码:

void handler(int sig_num) {
    (void)sig_num;
    interruption = 1;
}

And here's the code to install the handler: 这是安装处理程序的代码:

struct sigaction action = { 0 }; /* if your compiler frowns at it use {{ 0 }} */
action.sa_handler = handler;
sigaction(SIGINT, &action, NULL);

Now your program should work. 现在您的程序应该可以工作了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM