execlp使用管道dup2 - c语言的多个命令

时间:2013-04-12 12:35:14

标签: c fork dup2

我有一个小程序,它执行bash命令(一种shell程序)。

当用户发送如下命令时:

  
      
  1. ls -l | grep。[c,h] $ | wc -l <​​/ p>

  2.   
  3. LS

  4.   
  5. echo | LS

  6.   

我决定使用链表数据结构,这是执行

的功能
int execute(command *c) {
//create new procces and execute command 

int numOfPipe = getNumOfPipes(c);   // gets how many commands there is seperated by | (for 1 command with no pipes. getNumOfPipes returns 1
int fds[numOfPipe][2];

pid_t pids[numOfPipe];
int i;
int status;

// create pipes
for( i = 0; i < numOfPipe; i++ ) {
    pipe(fds[i]);
}

i=0;

// p set to be the head of the list (first command)
Pipe* p = c->pl->head;  

// running throw all nodes
while(i<numOfPipe) {

    if ((pids[i] = fork()) < 0) {
            perror("fork");
            abort();
    } else if (pids[i] == 0) {
        // children processes

        // there is more then one command
        if (numOfPipe > 1) {    
            if (p==c->pl->head) // first node (will be first command)
                dup2(fds[i][1],STDOUT_FILENO);
            else if(p->next!=NULL) {    // not first / last command
                dup2(fds[i-1][0],STDIN_FILENO);
                dup2(fds[i][1],STDOUT_FILENO);

            } else if(p->next==NULL)    // last command
                dup2(fds[i-1][0],STDIN_FILENO);


            // closing all pipes
            int j;
            for( j = 0; j < numOfPipe; j++ ){
                close(fds[j][0]);
                close(fds[j][1]);
            }
        }

        // execute command
        execvp(p->params[0],p->params);

        // on execute error will print this messege and returns COMMAND_ERROR
        fprintf(stderr, "%s: command not found\n",p->params[0]);    
        destroyShell(c);
        free(c);
        exit(COMMAND_ERROR);    
    }

    // parent closing all end of pipes
    int j;
    for( j = 0; j < numOfPipe && numOfPipe > 1; j++ ){
        close(fds[j][0]);
        close(fds[j][1]);
    }

    // waiting each process
    while(wait(&status)!=pids[i]);

    // if the command is valid
    if (WIFEXITED(status) && WEXITSTATUS(status)==COMMAND_ERROR) {
        destroyShell(c);
        return WEXITSTATUS(status);
    }

    p=p->next;
    i++;


}

// closing all end of pipes (necessary here????)
int j;
for (j = 0; j < numOfPipe; j++) {
    close(fds[j][0]);
    close(fds[j][1]);
}

// returns all command's return code
if (WIFEXITED(status))
    return WEXITSTATUS(status);

return 0;
}

现在这段代码以不可预测的方式工作,对于单一命令它的工作,对于serval有时它工作,有时不行....花了很多时间在这块代码和谷歌没有帮助!

很少注意到:

  1. 当用户发送如下命令时:
  2.   

    回波| LS | 123

    返回代码将是COMMAND_ERROR宏定义,并且出现此错误消息:

      

    123:找不到命令

    但不知怎的,我的代码将执行'echo | ls'并显示2个第一个命令的输出,之后将显示“123”命令的错误消息。 还有一些糟糕的命令 - 它只是为它发现的第一个显示错误信息,并且它不会继续执行下一个命令......

    并且对于此命令:

      

    ls -l | grep。[c,h] $ | wc -l <​​/ p>

    好像它无处不在地存在......

    1. 命令* c正在处理链表,列表中的每个节点都是一个命令,每个节点都将保留数组调用参数,这些参数保留了命令的所有参数。 〔实施例:
    2.   回声1234 | ls / home

       ___________                 ___________
      |           |               |           |
      | COMMAND 1 |      --->     | COMMAND 2 |
      |___________|               |___________|
            |                           |
            |                           |
          ______                     _______
         |      |                   |       |
         | ECHO |                   |  LS   |
         |______|                   |_______|
         |      |                   |       |
         | 1234 |                   | /HOME |
         |______|                   |_______|
      

      我希望我很清楚并且很好地解释了我的问题。 非常感谢你!

0 个答案:

没有答案