Saxophlutist
Saxophlutist

Reputation: 291

Attempting to implement redirection. Having trouble understanding file descriptors and dup2

I am supposed to be implementing a shell with redirection capabilities, but I am having trouble making heads or tails as to how to work with file descriptors. Here in my test.c file, I am experimenting, trying to pipe test from 'python --version' into a file called 'out'.

int main(int argc, char *argv[], char *const envp[])
{
/***/TOKENIZER *tester;
    int pid = 0;
    int pipefd[2];
    char buffer = 0;

    pipe(pipefd); 
    pid = fork();
    pipefd[1] = open("out", O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);

    if(pid == 0){
        close(pipefd[1]);
        dup2(pipefd[0], STDIN_FILENO); 
        close(pipefd[0]);
        while(read(STDIN_FILENO, &buffer, 1) > 0){
            write(STDOUT_FILENO, &buffer, 1);
        }

        close(pipefd[0]);
        _exit(EXIT_SUCCESS);
    }else{
        close(pipefd[0]);
        dup2(pipefd[1], STDOUT_FILENO); 
        close(pipefd[1]);

        write(STDOUT_FILENO, "asdsd\n", 6);

        char* ver[2];
        ver[1] = "--version";
        execvp("python", ver);
        exit(EXIT_SUCCESS);
    }
    free(tester);


    return 0;

EDIT: Realized I was mixing parts of redirection and piping up. Here is some redirection code which I am attempting to run.

int out = open("output.txt", O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);

dup2(out, 1);
close(out);

char* ver[2];
ver[1] = "--version";
execvp("python", ver);
exit(EXIT_SUCCESS);

return 0;

I am attempting to get the Python versioning into output.txt, but I seem to be missing something since it's not working.

EDIT 2: Looks like it's executing, but it's outputting to standard out instead of output.txt.

int out = open("output.txt", O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);
dup2(out, STDOUT_FILENO);

char* ver[3];
ver[0] = "python";
ver[1] = "--version";
ver[2] = NULL;
execvp("python", ver);
perror("exec");

return 0;

Upvotes: 3

Views: 405

Answers (1)

user2404501
user2404501

Reputation:

    int pid = 0;
    int pipefd[2];
    char buffer = 0;

    pipe(pipefd); 
    pid = fork();

So far, so good. You've created a pipe, with its two file descriptors stored in pipefd[0] and pipefd[1], and created a child process.

    pipefd[1] = open("out", O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);

Oh no! You just overwrote a perfectly good file descriptor (the write end of the pipe) with a different one, pointing to the regular file named "out".

Are you trying to do regular file redirection, or a pipe? Before you try to implement a shell, you should a least know that these are two different things. If you're trying to mimic python --version > out then you should notice that there's no pipe character in that command line, so why would you imagine that a pipe is involved in the implementation?

Also, since you did this after the fork, both processes are running now, and both of them are going to do the open, including the creating and truncating side effects. That can't be what you wanted.

I'll stop there, since the rest of the program won't make sense until you fix this part.

But a few random notes:

  • 3-arg main has been obsolete for quite some time. Use getenv() or environ to look up environment variables.
  • A single-byte buffer is not efficient, and it wouldn't be much harder to use a bigger one.
  • It's weird - not necessarily a fatal problem but definitely unusual - to do the exec in the parent and not in the child.

Upvotes: 1

Related Questions