zuto9999
zuto9999

Reputation: 47

Processing and Pipes

Premise: Implement a C++ program that prompts the user for 2 commands. Each input string should be a UNIX command, with arguments allowed. For example, input 1 could be "ls -l" and input 2 could be "wc -l". The program will then create a pipe, and two child processes. The first child process will run the command specified in the first input. It will output to the pipe instead of standard output. The second child process will run the command specified in the second input. It will take its input from the pipe rather than standard input. The parent process will wait on its two children to complete, then the whole thing will repeat. Execution will stop when "quit" is entered as the first command.

I believe I am almost done with the program but I am getting having trouble figuring out how to get the user input executed in the pipe, and I end up with syntax errors.

Here is my code so far:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cstring>
using namespace std;

int main() {
    //Declare Variables
    char first, second[80];
    int rs, pipefd[2];
    int pid1, pid2;
    char *command1[80], *command2[80];

    //Asking for the commands
    cout << "Please enter your first command(incl. args) or quit: ";
    cin >> first;

    //Do the program while the first answer isn't quit
    while(first[0] != 'quit') {

    //Copy first answer into first command
    strcpy(command1, ((char*)first);

    //Just skip to end of program if first command is quit
    cout << "Please enter your second command(incl. args): ";
    cin >> second;

    //Copy second answer into second command
    strcpy(command2, ((char*)first);

    //pipe
    rs = pipe(pipefd);
    //if pipe fails to be made
    if(rs == -1){
        perror("Fail to create a pipe");
        exit(EXIT_FAILURE);
    }

    //Fork for the two processes
    pid1 = fork();

    if (pid1 != 0){
    pid2 = fork();
}

    if(pid1 == -1){
        perror("Fail to create a pipe");
        exit(EXIT_FAILURE);
    }
        if(pid2 == -1){
        perror("Fail to create a pipe");
        exit(EXIT_FAILURE);
    }

        if (pid1 == 0) { // 1st child process   
        // close write end of pipe
        close(pipefd[0]);
        // duplicate
        dup2(pipefd[1], 1);
        //execute the input argument
        execvp(command1[0], command1);
    } 
                if (pid1 == 0) { // 2st child process   
        // close write end of pipe
        close(pipefd[0]);
        // duplicate
        dup2(pipefd[1], 1);
        //execute the input argument
        execvp(command2[0], command2);
    }

        else {  // parent process   
        // close read end of pipe
        close(pipefd[0]);
        // wait for child processes
        wait(&pid1);
        wait(&pid2);    
    }

    //Asking for the commands
    cout << "Please enter your first command(incl. args) or quit: ";
    cin >> first;

    }; //end of while()

return 0;
}

Any help/hints would be appreciated for this is due in the near future and I would love to finally have this beast tackled.

Edit: Adding errors gotten

In function int main()':
z1674058.cxx:26:33: error: expected ')' before ';' token
z1674058.cxx:33:33: error: expected ')' before ';' token

Upvotes: 0

Views: 1134

Answers (1)

John Kugelman
John Kugelman

Reputation: 362087

// close write end of pipe
close(pipefd[0]);
// duplicate
dup2(pipefd[1], 1);

You have these same two lines in both child #1 and child #2. The two children should do opposite operations here. One of them should be closing pipefd[1] and duping pipefd[0] to stdin.

You've also got some string-handling bugs.

char first, second[80];

This doesn't declare two 80-character arrays. It declares one char and one char[80]. I suspect this is why you put in the (char *) cast here—to silence a compiler error:

strcpy(command1, ((char*)first);

Don't do that. Don't use casts to shut the compiler up. The cast is covering up a serious error.

char *command1[80], *command2[80];

These declarations are also incorrect. This declares two arrays of 80 char *s apiece. That is, two arrays containing 80 strings each. I'll leave it up to you to figure out how to fix this...

Upvotes: 3

Related Questions