1
votes

I'm trying to redirect child process's input and output stream, without redirect parent process input and output stream. My idea was to check whether or not there is an input\output in the command line, if so to redirect to it, then fork and wait for child to complete it's process if necessary, and eventually redirect back to stdin and stdout. The problem is that this code somehow doesn't redirect back to stdin and stdout and the parent process stays in the previous streams. Here is my code:

typedef struct cmdLine
{
    char * const arguments[MAX_ARGUMENTS]; /* command line arguments (arg 0 is the command)*/
    int argCount;       /* number of arguments */
    char const *inputRedirect;  /* input redirection path. NULL if no input redirection */
    char const *outputRedirect; /* output redirection path. NULL if no output redirection */
    char blocking;  /* boolean indicating blocking/non-blocking */
    int idx;                /* index of current command in the chain of cmdLines (0 for the first) */
    struct cmdLine *next;   /* next cmdLine in chain */
} cmdLine;

void execute(cmdLine *pCmdLine){
    FILE * input = NULL;
    FILE * output = NULL;
    if(pCmdLine->inputRedirect != NULL){
        close(fileno(stdin));
        input = fopen(pCmdLine->inputRedirect, "r+"); //open for child
    }
    if(pCmdLine->outputRedirect != NULL){
        close(fileno(stdout));
        output = fopen(pCmdLine->outputRedirect, "ab+"); //open for child
    }
    pid = fork();
    if(pCmdLine->blocking == 1) {
        waitpid(pid, NULL, 0);  //wait for chile to finish
        if (input){     //redirect to stdin
            close(input);
            fopen(stdin, "r+");
            fflush(stdin);
        }

        if (output){    //redirect to stdout
            close(output);
            fopen(stdout, "ab+");
            fflush(stdout);
        }
    }
    if(pid == 0){
        execvp(pCmdLine-> arguments[0],pCmdLine->arguments);    //exec child
        perror("execution went wrong!");
        exit(-1);
    }
}

How should I do in correctly and elegant?

Notes: without using dup2 and pipe, or any other libraries rather than those: unistd.h,stdio.h,stdlib.h,string.h,sys/wait.h

1
There's no need for a pipe, but why not use dup or dup2?Olaf Dietsche
This was our demand and the instruction was that by closing the standard input stream or the standard output stream, and opening a new file, which in turn is automatically allocated with the lowest available file-descriptor index. This effectively overrides stdin or stdout.Avi Ferdman

1 Answers

1
votes

Redirecting shall be done by closing and reopening standard input and standard output respectively. And it shall be done in the child process only.

This may be done by doing it in the child branch

pid_t pid = fork();
if (pid == -1) {
    // error handling
    perror("fork");
} else if (pid == 0) {
    // Now we're in the child process
    if (pCmdLine->inputRedirect != NULL) {
        fclose(stdin);
        input = fopen(pCmdLine->inputRedirect, "r+"); // open for child
    }

    if (pCmdLine->outputRedirect != NULL) {
        fclose(stdout);
        output = fopen(pCmdLine->outputRedirect, "ab+"); // open for child
    }

    execvp(pCmdLine->arguments[0], pCmdLine->arguments); // exec child
    perror("execution went wrong!");
    exit(-1);
} else {
    // Now we're in the parent process
    waitpid(pid, NULL, 0);
}