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");

            }
Vineeth Sai
  • 1,497
  • 2
  • 9
  • 10
  • 2
    See [Redirection inside call to execvp() not working](https://stackoverflow.com/questions/13784269/redirection-inside-call-to-execvp-not-working) and please provide [**A Minimal, Complete, and Verifiable Example (MCVE)**](http://stackoverflow.com/help/mcve). This question appears to be a duplicate of the first link, but you have not provided enough information to make that determination. – David C. Rankin May 28 '18 at 03: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. – John Bollinger May 28 '18 at 03:40
  • The code looks good save for using 0 instead of STDIN_FILENO. `close(0)` is redundant [and inferior](http://man7.org/linux/man-pages/man2/dup.2.html). `dup2` and `close` can fail, although only if arguments are invalid. Can't say anything more, see prev comments. – ivan_pozdeev May 28 '18 at 03:52
  • Possible duplicate of https://stackoverflow.com/questions/14543443/in-c-how-do-you-redirect-stdin-stdout-stderr-to-files-when-making-an-execvp-or – ivan_pozdeev May 28 '18 at 03: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. – Vineeth Sai May 28 '18 at 04:04

1 Answers1

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
Rorschach
  • 31,301
  • 5
  • 78
  • 129
  • 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! – Vineeth Sai May 28 '18 at 05:05