我正在尝试让我的shell实现使用freopen将stdout和stdin从控制台重定向到输出文件,但当我尝试通过执行类似“ls> outfile.txt”的操作时,我的程序继续等待子进程,直到我强制停止它,强制停止后,输出文件成功创建,但我想知道我需要做什么来解决这个问题,我需要使用fclose()之后?下面是我的代码的一部分,如果你需要更多它让我知道,但基本上overrideOut是一个int我设置为1如果'>'是命令行中的倒数第二个arg。然后我尝试拆分>和使用execvp调用ls的路径参数,但我不确定我是否正确地执行此操作。谢谢大家。
while(1){
if((pid = fork()) != 0){
wait(&status);
printf("%i", overrideOut);
printf("Myshell> ");
fgets(buffer, 512, stdin);
if(buffer[strlen(buffer)-1] == '\n'){
buffer[strlen(buffer)-1] = '\0';
}else{
printf("\n");
return 0;
}
argv[0] = strtok(buffer, " \n\0");
for(argc=1; argv[argc-1]; argc++){
if(!strcmp("&", argv[argc-1])){
bg = 1;
}
if(!strcmp(">", argv[argc-1])){
overrideOut = 1;
}
if(!strcmp(">>", argv[argc-1])){
appendOut = 1;
}
if(!strcmp("<", argv[argc-1])){
overrideIn = 1;
}
if(!strcmp("<<", argv[argc-1])){
appendIn = 1;
}
argv[argc] = strtok(NULL, " \n\0");
}
if(!strcmp("exit", argv[0])) exit(0);
printf("Waiting for child (%d)\n", pid);
printf("Child (%d) finished\n", pid);
if(overrideOut == 1){
freopen(argv[argc-2], "w+", stdout);
//clear the > and path args to just call ls with execvp
argv[argc-2] = strtok(NULL, " \n\0");
argv[argc-3] = strtok(NULL, " \n\0");
//for(argc=0; argv[argc-1]; argc++)
//printf("argv[%d] = %s, ", argc, argv[argc]);
}else if(appendOut == 1){
freopen(argv[argc-2], "a", stdout);
argv[argc-2] = strtok(NULL, " \n\0");
argv[argc-3] = strtok(NULL, " \n\0");
}else{
freopen("/dev/tty", "rw", stdin);
}
}else{
if(buffer[0] != '\0'){
execvp(argv[0], argv);
printf("error\n");
return 0;
}else{
return 0;
}
}
}
答案 0 :(得分:5)
您可能希望研究一些简单的免费软件shell的实现,例如sash。您可能希望在成功调用后进行重定向
fork(2)您可以将dup2(2)与STDOUT_FILENO
一起使用(这比常数1更易于人类阅读。)
我建议在编写shell时处理整数文件描述符,而不是FILE*
句柄。
您可能不应该重定向父shell进程中的文件(仅在子进程中)。你可能应该在父shell进程中调用pipe(2)(也许不在子进程中)。
您忘记处理代码中fork
的失败。
阅读Advanced Linux Programming,这很好地解释了基本概念。
您的代码段不完整:显示您调用fork
的位置和方式非常重要(也可能会显示您如何调用execve
)。不要忘记测试所有三种情况:失败(fork
的结果为<0
),子进程(==0
),父shell进程(>0
)。