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

标签 c linux bash shell redirect

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

最佳答案

您可能想研究一些简单的免费软件 shell 的实现,例如 sash 。您可能想在成功调用后进行重定向 fork(2)你可以使用 dup2(2)STDOUT_FILENO (这比常数 1 更易于人类阅读)。

我建议使用整数文件描述符,而不是 FILE*编写 shell 时的句柄。

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

您忘记处理 fork 的失败在你的代码中。

阅读Advanced Linux Programming这很好地解释了基本概念。

您的代码片段不完整:显示您在何处以及如何调用 fork 非常重要(也许还显示您如何调用 execve )。不要忘记测试所有三种情况:失败( fork 的结果是 <0 )、子进程( ==0 )、父 shell 进程( >0 )。

关于c - 简单的 shell linux C 实现,使用 freopen 重定向 stdout,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19338478/

相关文章:

c - 如何在C中一一获取字符串的输入

c++ - C++ 宏展开的一个问题

linux - 将输出重定向到其他 Linux 分区

我可以从指针地址(在 Linux 上的 C 中)获取 NUMA 节点吗?

C程序判断一个数是否为素数

c - 使用 getchar 在 while 循环中添加 break 语句

linux - 修改Linux内核中的现有模块

linux - Bash 无法更改文件内容

linux - 删除 bash 中最后一个点的所有文本

ruby-on-rails - 如何即时将当前目录的 bin/path 添加到 PATH