1

So, Basically, I'm creating my own shell in C, which can handle redirection. My stdout redirection is working but my stdin redirection does not work.

I'm trying to redirect stdin for Examples:

            hw9> cat < out.txt
            hw9> grep if < out.txt

My code:

            if(strcmp(token[i],"<")==0)
            {
                token[i]=NULL;
                int fd0;

                if ((fd0 = open(token[i + 1], O_RDONLY)) < 0)
                {
                    perror("Couldn't open input file");
                    exit(0);
                }
                close(0);
                // dup2() copies content of fdo in input of preceeding file
                dup2(fd0, 0); // STDIN_FILENO here can be replaced by 0

                close(fd0); // necessary
            }

This is my if block to check and perform stdin redirection but this doesn't seem to work. The expected output for cat out.txt is "helloo" and that should be the same output for cat < out.txt because the redirection will correspond to cat out.txt. But cat < out.txt doesn't give any output. The content of the file out.txt is "helloo".

hw9> cat out.txt

Tokens:
[0] 'cat'
[1] 'out.txt'
"helloo"
hw9> cat < out.txt

Tokens:
[0] 'cat'
[1] '<'
[2] 'out.txt'
hw9>

As you can see, the first call provides the correct output as expected but the second call does not prove any output. Let me know if you need any more information. I tried multiple other ways, but nothing seems to work. Thanks in advance!

Edit: I got it to work! My mistake was calling the execvp() outside the if block. I called it inside the if-block, and it seems to work! Thanks guys!

Final code:

            if(strcmp(token[i],"<")==0)
            {
                token[i]=NULL;
                int fd0;

                if ((fd0 = open(token[i + 1], O_RDONLY)) < 0)
                {
                    perror("Couldn't open input file");
                    exit(0);
                }
                close(0);
                // dup2() copies content of fdo in input of preceeding file
                dup2(fd0, 0); // STDIN_FILENO here can be replaced by 0
                close(fd0); // necessary
                execvp(*token, token);
                perror("execvp");

            }
5
  • 2
    See Redirection inside call to execvp() not working and please provide A Minimal, Complete, and Verifiable Example (MCVE). This question appears to be a duplicate of the first link, but you have not provided enough information to make that determination. Commented May 28, 2018 at 3:37
  • "Doesn't seem to work" is not enough to go on. Note well that an MCVE such as you've been asked for should include a detailed description of the actual observed behavior, and of how that differs from the behavior you want. Commented May 28, 2018 at 3:40
  • The code looks good save for using 0 instead of STDIN_FILENO. close(0) is redundant and inferior. dup2 and close can fail, although only if arguments are invalid. Can't say anything more, see prev comments. Commented May 28, 2018 at 3:52
  • Possible duplicate of stackoverflow.com/questions/14543443/… Commented May 28, 2018 at 3:52
  • I don't think it is a duplicate of the links above because I'm wondering what is wrong with my code rather than trying a different approach. Commented May 28, 2018 at 4:04

1 Answer 1

2

There isn't anything wrong with your code as far as I can tell. There error probably lies elsewhere, perhaps where you are calling exec. For example,

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

int main(int argc, char *argv[]) {
    int fd0;
    char *args[3] = { NULL };
    args[0] = argv[1];

    if (strcmp(argv[2], "<") == 0) {
        if ((fd0 = open(argv[3], O_RDONLY)) < 0) {
            perror("open");
            exit(1);
        }

        dup2(fd0, STDIN_FILENO);
        close(fd0);

        execvp(argv[1], args);

    } else {
        args[1] = argv[2];
        execvp(argv[1], args);
    }

    return EXIT_SUCCESS;
}

Calling the above test.out I see the expected output, calling without redirection,

./test.out cat test.c

And with redirection (quoted since the shell would do its own redirection)

./test.out cat '<' test.c
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot for showing where to call execvp(). I was calling the execvp() outside the if-else block which is why it probably not working. It's working now!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.