我的程序是基本的小外壳。 它允许您以参数ls,cd ...的形式在PATH中运行程序。 要从终端“ ./myshell2”运行程序类型,它将启动,您可以插入所需的命令。
它启动子进程,运行execvp,返回并重新启动,因此您可以键入新命令。 当键入“ Q”或“ q”时,整个程序应终止。 问题是我不知道如何停止它,下面的代码。 我的想法是,当键入“ Q”或“ q”时,杀死所创建的子进程并发送信号以消除其错误终止(子进程)。 因此(来自父项的)最终状态将不是1,并且该函数返回。 我评论了代码的某些部分,希望它更容易理解。 它起作用的问题是要停止它,我需要ctrlC。 我想对子进程说,他必须以一个非零值结尾。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include <signal.h>
int main(int argc, char * argv[]) {
while(1)
{
pid_t pid = fork();
if (pid == -1) {
perror("fork error");
exit(EXIT_FAILURE);
}
if (pid == 0) { // child process
printf("type the command to start (and arguments if required) \n"
"Q to quit\n");
char *dest[10]; // allow you to insert
char line[4096];//commands from terminal
if (fgets(line,sizeof(line),stdin)==0) return 1;
int i;
line[strcspn(line, "\n")] = '\0';
char *st = line;
for (i=0; i< 10 && (dest[i]=strsep(&st," "))!=NULL;i++)
continue;//now you typed the command
if ( ( memcmp(dest[0],"Q",1)==0 ) // if Q or q the program
|| (memcmp(dest[0],"q",1)==0) ) //must end
{
printf("got it!\n");
if (kill(getpid(),SIGSEGV)==-1) printf("kill error\n");
//in theory the process should terminates with bad status
// and the value of the variable "status" 'll be not 0
// I think that the problem is in this part of the code
}
if( strcmp(dest[0]," ")!=0 )
{
int res = execvp(dest[0], dest);
}
else
{ int res= execvp(dest[1],dest+1);}
perror("execvp error");
exit(EXIT_FAILURE);
}
int status;
pid_t child = wait(&status);
if (child == -1) {
perror("wait error");
exit(EXIT_FAILURE);
}
if (status==1)
break; //so it can exit from the loop that creates new process
setenv("WAIT","TRUE",0); //dont' worry about
//perror("setenv error\n");
if (memcmp("TRUE",getenv("WAIT"),4) == 0 ) //these 6 lines
printf("WAIT=TRUE\n");
else if(memcmp("FALSE",getenv("WAIT"),4) == 0 )
printf("WAIT=FALSE\n");
printf("end current process (status=%d, child=%d)\n", WEXITSTATUS(status), son);
}
return EXIT_SUCCESS;
}
答案 0 :(得分:3)
在所有情况下,您都将打印WEXITSTATUS()
,但这是不对的。您需要使用wait
检查WIFEXITED()
返回的状态是否是退出状态。如果非零,则孩子正常退出。否则,您可以使用WIFSIGNALED()
查看孩子是否被解雇,并且您将从WTERMSIG()
处获得信号
if(WIFEXITED(status))
{
printf("end current process (status=%d, child=%d)\n", WEXITSTATUS(status), son);
}
else if(WIFSIGNALED(status))
{
printf("end current process (signal=%d, child=%d)\n", WTERMSIG(status), son);
}
您确实应该让父进程处理命令的输入,而让子进程运行它。