简单的shell linux C实现,用freopen重定向stdout

par*_*ter 2 c linux bash shell redirect

我试图通过使用freopen将我的shell实现从控制台重定向stdout和stdin到输出文件,但是当我尝试通过执行类似"ls> outfile.txt"的操作时,我的程序继续等待子进程,直到我强制停止它,强制停止后,输出文件成功创建,但我想知道我需要做什么来解决这个问题,我之后需要使用fclose()吗?下面是我的代码的一部分,如果你需要更多它让我知道,但基本上overrideOut是一个int我设置为1如果'>'是命令行中的倒数第二个arg.然后我尝试将>和path参数拆分为仅使用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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Bas*_*tch 5

您可能想要研究一些像sash这样的简单免费软件shell的实现.你可能想要做的重定向的成功调用后 叉(2) ,你可以使用DUP2(2)STDOUT_FILENO(哪个更可读的不仅仅是常数1).

我建议FILE*在编写shell时处理整数文件描述符,而不是 句柄.

您可能不应该重定向父shell进程中的文件(仅在子进程中).您可能应该在父shell进程中调用pipe(2)(可能不在子进程中).

您忘记处理fork代码中的失败.

阅读高级Linux编程,它很好地解释了基本概念.

您的代码段不完整:显示您呼叫的位置和方式非常重要fork(也可能显示您的呼叫方式execve).不要忘了测试所有三种情况:失败(含的结果fork<0),子进程(==0),父shell进程(>0).