簡體   English   中英

為什么從我的 shell 中的 pipe 獲取輸入時,execvp() 中的 wc 命令會返回錯誤的結果?

[英]Why does wc command in execvp() return the wrong results when taking input from a pipe in my shell?

我正在為學習目的在 C 中編寫 shell ,並且我正在嘗試允許可變數量的管道。 一般來說,它似乎工作得很好。 但我注意到wc命令有問題。

當我把另一個程序的 pipe 一些 output 放到wc中時,就像ls | wc ls | wc它總是返回
1 3 35不管我用pipe 進去吧。 當我 pipe 進入它們時,其他命令按預期工作。 在我正常的zsh shell wc工作正常。 我正在努力尋找問題所在。 我嘗試在分叉后添加waitpid ,但沒有骰子。

這是主要 function 中的main shell 循環:

while (1) {
        printf("\033[31;1mshell:\033[0m ");

        line = read_cmds();

        if (strstr(line, "|")) {
            // check for pipes first
            pipe_exec(line);
        } else {
            // we have a single command
            tokens = split(line, " \t\r\n");
            if (*tokens != NULL) shell_exec(tokens);
            free(tokens);
        }
    }

這是循環執行命令的 function:

void pipe_exec(char *line)
{
    int in, status;
    int pipe_no; // keep track of ptr to bring it back to free 
    int pfd[2];
    pid_t rc;
    char **cmd, **pipe_cmds;
    
    // split takes a string and splits into array of strings based on delimiter
    pipe_cmds = split(line, "|"); 

    in = 0;
    pipe_no = 0;
    while (*pipe_cmds) {
        cmd = split(*pipe_cmds, " \t\r\n");

        if (pipe(pfd) < 0) perror("pipe");

        make_proc(in, pfd[1], cmd);
        close(pfd[1]);
        in = pfd[0];
        pipe_cmds++; // move ptr ahead one
        pipe_no++;
    }
    // move pointer back and free
    pipe_cmds -= pipe_no;
    free(pipe_cmds);

    rc = fork();
    if (rc == 0) {
        if (in != 0) dup2(in, STDIN_FILENO);
        execvp(*cmd, cmd);
    } 
}

然后上面的make_proc調用的 make_proc function :

void make_proc(int in, int out, char **cmd)
{
    pid_t rc;
    rc = fork();
    if (rc  == 0) {
        if (in != STDIN_FILENO) {
            dup2(in, STDIN_FILENO);
            close(in);
        }
        if (out != STDOUT_FILENO) {
            dup2(out, STDOUT_FILENO);
            close(out);
        }
        execvp(*cmd, cmd);
    } 
}

我在這里取出了一些錯誤檢查以節省空間。 任何幫助表示贊賞!

您執行最后一個命令兩次,pipe 它的第一個實例到第二個。 添加類似:

    while (*pipe_cmds) { 
        cmd = split(*pipe_cmds, " \t\r\n");
        if (!pipe_cmds[1]) {
            break;
        }

        if (pipe(pfd) < 0) perror("pipe");

        make_proc(in, pfd[1], cmd);
        close(pfd[1]);
        in = pfd[0];
        pipe_cmds++; // move ptr ahead one
        pipe_no++;
    }

會阻止不必要的實例,盡管我寧願稍微重構一下這個 function。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM