【发布时间】:2020-10-31 23:01:18
【问题描述】:
当接收到 SIGINT 信号时,bash shell 退出用户当前正在编写的行,并打印出一个新的提示,但它并没有退出。我怎样才能模仿这种行为?我正在编写自己的 shell,我希望 shell 继续在 SIGINT 上运行。我不确定如何正确终止以前的fget 从标准输入读取然后打印出新提示:
我的代码:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
char *get_args()
{
char *args = calloc(sizeof(char), 1024);
fgets(args, 1023, stdin);
char *pter = strrchr(args, '\n');
if (pter)
*pter = 0;
return args;
}
void sigintHandler(int sig_num)
{
// Reset handler to catch SIGINT next time.
signal(SIGINT, sigintHandler);
printf("Received ctrl c\n");
}
int main(int argc, char *argv[])
{
char host_name[64]; // hostname
gethostname(host_name, 64);
signal(SIGINT, sigintHandler);
while (1)
{
if (isatty(STDIN_FILENO))
{
printf("[%s]$ ", host_name);
char *line = get_args();
printf("\nline: %s\n", line);
}
}
return 0;
};
如何在 SIGINT 之后终止 fgets 的运行,以便再次打印提示符(主机名)?
【问题讨论】:
-
您不能从信号处理程序调用 printf。你真的不应该。
-
这是一个调试语句,以确保我收到了 SIGINT,但我不确定如何从读取中终止前一个 fget 并重新开始循环以便打印提示。
-
可能导致错误的调试语句实际上是错误语句。君斯特不要这样做。即使它最初似乎有效。它会咬回来。
-
有两种方法:1)设置(全局)标志 2)siglongjump。阅读史蒂文斯了解详情。可能还有第三种方式,我不确定。
-
会使用 siglongjump 杀死 fget,因为它仍然会从标准输入读取