【问题标题】:Linux | Shell implementation in C | redirected file includes the promptLinux | C 中的 Shell 实现 |重定向文件包含提示
【发布时间】:2016-09-06 05:37:47
【问题描述】:

我正在用 C 实现 linux shell,但我的输出重定向似乎无法正常工作。当我运行“ls > testFile”时,我只是得到一个空提示,而我期待“minishell>”,我在打开 testFile 时找到了它。为什么会这样?这是重定向功能本身的问题还是包含重定向的功能的问题? (parse_line 或 process_cmd)

int main(void) {
    char cmdline[MAXLINE];
    while (1) {
        // print prompt
        printf("%s", prompt);
        fflush(stdout);

        // get user input
        if (fgets(cmdline, MAXLINE, stdin) == NULL) {
            return 1;
        } else {
            process_cmd(cmdline);

            fflush(stdout);
        }
}

    return 0;
}

void process_cmd(char *cmdline) {
    int argc;
    char *argv[MAXARGS];
    int status; 

    argc = parse_line(cmdline, argv);

    if (argc == 0) {
        return;
    }

    if (builtin_cmd(argc, argv) == 1) {
        int pid = fork(); 

        if (pid == 0) { 
            argv[argc] = NULL;

            if (execvp(argv[0], argv) == -1) {
                perror ("Error");
            }

            printf("%s: command not found.\n", argv[0]);
            exit(1); 
        }
    wait(&status); 
    }
    return;
}

int parse_line(char *cmdline, char **argv) {
    int count = 0;
    int isRedirected = -1;
    argv[0] = strtok(cmdline, delimiter);


    if (argv[0] == NULL) {
        return 0;
    }

    count++;

    while(1) {
        argv[count] = strtok(NULL, delimiter);
        if (argv[count] == NULL) {
            break;
        }
        count++;
    }

    // redirection check
    for (int index = 0; index < count; index++) {
        if ((strcmp(argv[index], ">") == 0)) {
            if (argv[index+1] == NULL) {
                printf("output file missing.\n");
                printf("USAGE: [command] > [target_file_name]\n");
                return count;
            }
            isRedirected = redirect(argv[index+1]);
            for ( index = index+2; index != count; index++) {
                argv[index-2] = argv[index];
            }
            argv[count-1] = NULL;
            argv[count-2] = NULL;
            count = count - 2;
            break;
        }
    }

    if (isRedirected > 0) {
        reverseRedirected(isRedirected);
    }


    return count;

}

int redirect(char *redirectionDest) {
    int stdOutputFd;
    int fd = open(redirectionDest,O_CREAT|O_TRUNC|O_WRONLY,S_IRUSR|S_IWUSR);
    if ((stdOutputFd = dup(1)) == -1) { 
        perror("Error");
        return -1;
    }
    if (dup2(fd, 1) == -1) { 
        perror("Error");
        close(stdOutputFd);
        return -1;
    }

    close(fd);

    return stdOutputFd;
}

void reverseRedirected(int fd) {
    if (dup2(1, fd) == -1) {
        printf("fd dup failed!!\n");
        exit(0);
    }

    return;
}

【问题讨论】:

  • 除非你喜欢麻烦,否则做fork和exec之间的重定向。这样您就不必取消重定向任何内容,也不必关心(取消)重定向失败的后果。
  • 如果它是非内置函数,那会很完美,但如果我想重定向我的内置函数怎么办?还有其他方法可以避免取消重定向吗?
  • 也分叉它们(不要执行,只分叉)。
  • 很抱歉一次又一次地询问......但我认为“内置函数”的措辞有点模棱两可。 'builtin-cmd' 函数运行我自己编写的函数,而不是位于 /bin 中的 linux 内置函数。它不调用 exec()。我还需要 fork() 吗?
  • 我明白这一点。这就是为什么我说“不要执行”。没有什么可以执行的。分叉,重定向,做内置的事情,等待。它比重定向更容易,做内置的事情,重定向回来,处理重定向错误。您已经有了分叉和等待代码。

标签: c linux shell redirect


【解决方案1】:

命令完成后您永远不会取消重定向,因此 shell 的输出会继续转到重定向的文件描述符。

编辑:

我还刚刚注意到:您的 reverseRedirected 函数(在 redirect 函数中被不正确地调用,而不是在命令完成后调用)的 dup2 参数顺序错误。

【讨论】:

  • 取消重定向是什么意思?
  • 您在解析命令行时重定向文件描述符 1 - 而您仍然是“shell”。在你 fork 之后,运行命令并等待它执行,文件描述符 1 仍然被重定向。您需要 (a) 在命令返回后撤消重定向,或者 (b) 在子分支中实现重定向本身,而不是在 shell 中。
  • 嗯...只是一个青少年的事情,像这样的问题真的应该是cmets而不是答案,只是说......
  • @AdelK 抱歉,我将我的答案表述为一个问题,不应该有。我已经改写了。
  • 在命令完成后移动了 reverseRedirection,并更改了参数的顺序。现在它可以工作了!多谢。它也回答了我的其他好奇心。看来我误解了重定向的概念。
猜你喜欢
  • 2012-11-13
  • 1970-01-01
  • 1970-01-01
  • 2013-11-19
  • 2013-10-20
  • 2012-03-06
  • 2015-04-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多