在c

时间:2017-05-11 14:02:28

标签: c process pipe fork

我一直在努力创建一个程序来读取shell命令并像

那样执行它们
ls -l | sort > there.txt

然而,我所做的并没有执行第二个命令。 我仍然是c编程的新手,我根本不熟悉fork()和pipe(),所以如果我所做的事情有很多错误我也不会感到惊讶。 如果有人可以帮助我会很感激。 提前谢谢

这是我的代码:

COMMON.H

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>

void runThat(char* cmd1[], char* cmd2[]);

common.c:

#include "common.h"
void runThat(char* cmd1[], char *cmd2[]){
    pid_t pid, waitPid;
    int pipefd[2];
    int status;
    pipe(pipefd);
    pid = fork();

    if (pid<0){
        perror("Fork has failed");
        exit(1);
    }
    else if (pid==0){
        dup2(pipefd[0],0);
        close(pipefd[1]);
        if (execvp(cmd1[0],cmd1)==-1){
            perror("Error");
            exit(1);
        }
    }
    else{
        waitPid = wait(&status);
        if (waitPid == -1){
            perror("Waitpid failed");
            exit(1);
        }
        dup2(pipefd[1],1);
        close(pipefd[0]);


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

主要是:

#include "common.h"

#define BUFFER 300


int main(void){

    char * buffer = (char*)malloc(sizeof(char)* BUFFER);
    unsigned int buffer_length;
    char* tkn;
    char * param[BUFFER];
    char * cmd1[BUFFER];
    char * cmd2[BUFFER];
    char *filename = NULL;
    char *output = NULL;
    int append = 0;
    int f1;
    int f2;
    int saved_stdin = dup(0);
    int saved_stdout = dup(1);

    printf("mysh4> ");

    while (1){  
        filename = NULL;
        output = NULL;
        memset(buffer,0,BUFFER);
        int input = getline(&buffer,&buffer_length,stdin);

        if (input==-1){
            printf("\n");
            exit(1);
        }

        if (input>BUFFER){
            printf("Error. Comand must not exceed %d characters.\n",BUFFER);
            exit(1);
        }

        switch(input){
            case 1:
                printf("mysh4> ");
                break;

            default:
                if ((strcmp(buffer,"exit\n")==0)||(strcmp(buffer,"terma\n")==0)||(strcmp(buffer,"end\n")==0)) {
                    printf("EXIT\n");
                    exit(1);
                }
                else {
                    int i =0; int j=0;
                    tkn = strtok(buffer," \t\n");
                    int NOP = 0;
                    while (tkn != NULL){
                        if(strcmp(tkn,"<")==0){
                            filename = tkn = strtok(NULL," \t\n");
                        }
                        else if(strcmp(tkn,">")==0){
                            output = tkn = strtok(NULL," \t\n");
                            append =0;
                        }
                        else if(strcmp(tkn,">>")==0){
                            output = tkn = strtok(NULL," \t\n");
                            append =1;
                        }
                        if(strcmp(tkn,"|")==0){
                            NOP++;
                            //param[i++] = NULL;    
                        }
                        //else
                            param[i++] = tkn; 
                        tkn = strtok(NULL, " \t\n");    
                    }
                    param[i] = NULL;
                    i=0; j=0;
                    while (param[i]!= NULL){
                        if (strcmp(param[i],"|")==0) break;
                        cmd1[i] = param[i];
                        i++;
                    }

                    cmd1[i] = NULL;

                    while (param[i]!=NULL){
                        if (strcmp(param[i],"|")==0) i++;
                        cmd2[j] = param[i];
                        j++; i++;
                    }
                    cmd2[j] = NULL;

                    i=0;
                    while (cmd1[i]!=NULL){
                        printf("cmd1 HAS:[%s]\n", cmd1[i++]);               // TO BE DELETED
                        if (cmd1[i]==NULL){
                            printf("cmd1 HAS:[NULL]\n");
                        }
                    }

                    i=0;
                    while (cmd2[i]!=NULL){
                        printf("cmd2 HAS:[%s]\n", cmd2[i++]);               // TO BE DELETED
                        if (cmd2[i]==NULL){
                            printf("cmd2 HAS:[NULL]\n");
                        }
                    }

                    printf("FILENAME :[%s]\n", filename);
                    printf("OUTPUT: [%s]\n", output);

                    if (filename){
                        f1 = open(filename,O_APPEND | O_RDONLY);
                        if(dup2(f1,0) < 0) {
                            perror("Dup2:Input failed."); exit(1);
                        }
                        close(f1);
                    }

                    if (output){
                        if(append == 0)
                            f2 = open(output,O_WRONLY | O_CREAT | O_TRUNC, 0777);//TRUNC:ta sbhnei
                        else
                            f2 = open(output,O_WRONLY | O_CREAT | O_APPEND, 0777);
                        if(dup2(f2,1) < 0) {
                            perror("Dup2:Output failed."); exit(1);
                        }               
                        close(f2);
                    }

                    runThat(cmd1,cmd2);

                    dup2(saved_stdin,0);    
                    dup2(saved_stdout,1);   

                    printf("mysh4> ");
                    break;


                }//else

        }//switch
    }//while

    free(buffer);
    return 0;
}

编辑:经过大量搜索后,我发现了一些与我有类似问题的人发帖。在我的程序中应用建议的答案我最终得到了以下功能。但是,现在当我输入像“ls -l”这样的命令时,它似乎运行了两次

total 40
-rw-rw-r-- 1 csuser csuser  1553 Μάι  12 18:27 common.c
-rw-rw-r-- 1 csuser csuser   313 Μάι  12 17:00 common.h
-rwxrwxr-x 1 csuser csuser 12204 Μάι  12 18:25 m
-rw-rw-r-- 1 csuser csuser  2534 Μάι  12 18:00 mysh4.c
-rw-rw-r-- 1 csuser csuser  7395 Μάι  12 12:44 p3090278-mysh4.c
-rwxrwxr-x 1 csuser csuser    59 Μάι  12 17:46 that
-rwxrwxr-x 1 csuser csuser    22 Μάι  12 18:13 there
csuser@CSLAB2:~/Desktop$ total 40
-rw-rw-r-- 1 csuser csuser  1553 Μάι  12 18:27 common.c
-rw-rw-r-- 1 csuser csuser   313 Μάι  12 17:00 common.h
-rwxrwxr-x 1 csuser csuser 12204 Μάι  12 18:25 m
-rw-rw-r-- 1 csuser csuser  2534 Μάι  12 18:00 mysh4.c
-rw-rw-r-- 1 csuser csuser  7395 Μάι  12 12:44 p3090278-mysh4.c
-rwxrwxr-x 1 csuser csuser    59 Μάι  12 17:46 that
-rwxrwxr-x 1 csuser csuser    22 Μάι  12 18:13 there

我也编辑了我的主要课程,但我测试了它并且没有任何问题,所以下面的代码再次出现问题。它应该能够运行无管道或多管道

void runThat(char *cmds[][MAX_PAR], int NOP){
    pid_t pid, waitPid;
    int status;
    int pipefd[2];
    int Num_Cmds = NOP +1;
    int r[Num_Cmds]; int w[Num_Cmds];
    char ** cmd;

    for (int i = 0; i < Num_Cmds; i++){
        r[i] = -1;
        w[i] = -1;
    }

    for (int j = 0; j < NOP; j++){
        pipe(pipefd);
        r[j+1] = pipefd[0];
        w[j] = pipefd[1];
    }

    for (int i = 0; i < Num_Cmds; i++){

        int h = 0;
        while (cmds[i][h]!= NULL){
            cmd[h] = cmds[i][h];
            printf("This [%s]\n", cmd[h]);
            h++;
        }
        cmd[h] = NULL;
        printf("This [%s]\n", cmd[h]);

        if (pid = fork() < 0){
            perror("Fork has failed");
            exit(1);
        }
        else if(pid == 0){
            if (r[i] != -1){
                close(STDIN_FILENO);
                dup2(r[i],STDIN_FILENO);
            }
            if (w[i] != -1){
                close(STDOUT_FILENO);
                dup2(w[i],STDOUT_FILENO);
            }
            for (int j = 0; j < Num_Cmds; j++){
                close(w[j]);
                close(r[j]);
            }
            if (execvp(cmd[0], cmd)==-1){
                perror("Command Failed");
                exit(0);
            }
        }
        else{
            waitPid = wait(&status);
            if (waitPid == -1){
                perror("Waitpid failed");
                exit(1);
            }
            close(w[i]);
            if (i>0){
                close(r[i]);
            }
        }   
    }
}

0 个答案:

没有答案