如何将新行字符发送到c中的stdin并允许fgets(cmdline、MAXLINE、stdin)接收它?
我目前正在用c语言构建一个shell程序。 我需要使用signals来捕获CTRL-C信号,并输出use-exit来请求用户使用我的内置命令exit离开myshell。 我已将信号处理程序添加到输出Use exit,但无法使shell在Use exit后输出[/]> 预期成果:如何将新行字符发送到c中的stdin并允许fgets(cmdline、MAXLINE、stdin)接收它?,c,linux,shell,C,Linux,Shell,我目前正在用c语言构建一个shell程序。 我需要使用signals来捕获CTRL-C信号,并输出use-exit来请求用户使用我的内置命令exit离开myshell。 我已将信号处理程序添加到输出Use exit,但无法使shell在Use exit后输出[/]> 预期成果: [assignment2] > ^C Use exit [assignment2] > ^C Use exit [assignment2] > ^C Use exit [assignment2] >
[assignment2] > ^C
Use exit
[assignment2] > ^C
Use exit
[assignment2] > ^C
Use exit
[assignment2] > exit
但是,我的程序的输出没有[assignment2]>输出。每次退出^C Use后,我必须按键盘上的enter键才能显示[assignment2]>:
[assignment2] > ^C
Use exit
^C
Use exit
^C
Use exit
[assignment2] > exit
我怀疑在处理信号后,程序仍然卡在fgetscmdline、MAXLINE、stdin中,因此程序不会继续到while循环的开头打印出[assignment2]>,如下代码所示:
myshell和handle信号函数的代码:
// Signal handler funciton
void handler(int signal){
switch(signal) {
case SIGINT:
write(STDOUT_FILENO, "\nUse exit\n", 10);
break;
case SIGTSTP:
write(STDOUT_FILENO, "\nUse exit\n", 10);
break;
case SIGQUIT:
write(STDOUT_FILENO, "\nUse exit\n", 10);
break;
}
int main(){
// Add signal handler
if (signal(SIGINT, handler) == SIG_ERR) {
perror("signal");
} else if (signal(SIGTSTP, handler) == SIG_ERR){
perror("signal");
} else if (signal(SIGQUIT, handler) == SIG_ERR){
perror("signal");
}
// ...... init cmdline and cwd char
while(1){
char dir[MAXPATH];
getcwd(cwd, sizeof(cwd));
printf("[%s] > ", parsecwd(cwd));
if (get_cmd_line(cmdline) == -1) // The program is stuck inside this funciton
continue; /* empty line handling */
eval(cmdline); /* Evaluate and process the cmd input*/
}
}
int get_cmd_line(char *cmdline)
{
int i;
int n;
if (!fgets(cmdline, MAXLINE, stdin)) // The program is stuck in this fgets
return -1;
// Ignore the newline character
n = strlen(cmdline);
cmdline[--n] = '\0';
i = 0;
while (i < n && cmdline[i] == ' ') {
++i;
}
if (i == n) {
// Empty command
return -1;
}
return 0;
}
但这并不能解决问题,它只是在终端中打印出一行新行
你知道怎么解决这个问题吗?
谢谢。的标准库glibc实现使用BSD语义,这意味着系统调用将在信号出现时重新启动而不是失败 此行为使FGET等在信号处理程序完成时不返回 要控制此行为,请改用建议的函数。更具体地说,确保未设置SA_重启标志:
struct sigaction action = { 0 }; // Initialize all members to zero or null
action.sa_handler = &handler;
sigaction(SIGINT, &action, NULL);
这样,fgets函数将返回一个空指针,errno应等于EINTR。的标准库glibc实现使用BSD语义,这意味着系统调用将在信号发生时重新启动而不是失败 此行为使FGET等在信号处理程序完成时不返回 要控制此行为,请改用建议的函数。更具体地说,确保未设置SA_重启标志:
struct sigaction action = { 0 }; // Initialize all members to zero or null
action.sa_handler = &handler;
sigaction(SIGINT, &action, NULL);
这样,fgets函数将返回一个空指针,errno应该等于EINTR