0

I have two processes, father and child, that need to execute two commands, synchronizing with pipes. A text file containing these commands on two different lines is given in input to the program. So it would be something like this:
ps aux
wc -l
I found other questions about more or less the same problem but I haven't figured out what could be wrong here.

void write_to_pipe(int pipeIn[], char *commands_file){

    FILE *command_stream ;
    char *line = NULL ; //contains the first command
    char *command, *options[200] ;
    int i = 0 ;

    close(STDOUT_FILENO);
    if(dup(pipeIn[1])== -1){
        perror("Duplication failed");
        exit(1);
    }
    close(pipeIn[0]);
    close(pipeIn[1]);
    command_stream = fopen(commands_file,"r");
    if (getline(&line, 0, command_stream)!= -1){
            fclose(command_stream);
            command = strtok(line," ");//tokenize string with a separator
            options[i++] = command ;
            while((options[i] = strtok(line," "))!= NULL){
                    i++ ;
            }
            execvp(command, options);
            perror("execvp failed");
            exit(1);


    }

}

This function uses dup to redirect stdout to the pipe. Then, it opens the file in input and calls execvp using the first token of the line as the command and the rest as arguments. The read function is very similar

    void read_from_pipe(int pipeIn[], char *commands_file){

    FILE *command_stream ;
    char *line = NULL ; //contains the second command
    char *command, *options[200] ;
    int i = 0 ;

    close(STDIN_FILENO);
    if(dup(pipeIn[0])== -1){
         perror("Duplication failed");
         exit(1);
    }
    close(pipeIn[1]);
    close(pipeIn[0]);
    command_stream = fopen(commands_file,"r");
    getline(&line, 0, command_stream);
    if (getline(&line, 0, command_stream)!= -1){
            fclose(command_stream);
            command = strtok(line," ");//tokenize string with a separator
            options[i++] = command;
            while((options[i] = strtok(line," "))!= NULL){
                    i++ ;
            }
            execvp(command, options);
            perror("execvp failed");
            exit(1);


    }

}

The only difference being that getline is called once more to skip the first line, because the reader has to execute the second command. And then there's the main:

int main(int argc, char *argv[]){
    //if no file is given the program does nothing
    if (argv[1]){

            pid_t pid ;
            int mypipe[2] ;

            if (pipe(mypipe)){
                    //pipe creation has failed
                    perror("Pipe creation failed");
                    exit(1);
            }

            pid = fork();

            switch(pid){
                    case 0:
                            read_from_pipe(mypipe,argv[1]);
                            break;

                    case -1:
                            perror("Fork failed");
                            break;

                    default:
                            write_to_pipe(mypipe,argv[1]);
                            break;
            }
    }
    return 0 ;
 }

The program compiles and it runs but it outputs nothing.

[Edit] Adjusted execvp to have the command in the arguments array and checked for errors with dup. Still gives no output.

Plutone11011
  • 127
  • 3
  • 10
  • I would check the return code from `dup` to make sure it worked. If it failed, the `errno` would be helpful. – bruceg Mar 18 '19 at 19:31
  • 1
    "it [...] calls execvp using the first token of the line as the command and the rest as arguments" -- yes, but that's incorrect. The program will expect the zeroth element of its `argv` array to be the name, path, or label of the program. The command-line arguments should start from index 1. That's not automagic -- the program just gets the `argv` you specify. For the exec'd commands to interpret their arguments correctly, therefore, you must avoid separating the command from them. – John Bollinger Mar 18 '19 at 19:36

0 Answers0