0

Working on the implementation of a shell program, and I've run into an issue with one of functions. Scaled down, it's regarding standard input redirection with built in functions. In particular, I'm implementing a built in function to "pause" the system until the user hits enter. Since this is taking input from stdin, it should be able to work if I have previously redirected stdin using dup2() to another file. I have been able to redirect stdin and read from the input file without a problem, but the problem that I am getting is after I "clean up" and reset stdin back to its initial state, which I saved with dup().

The problem isn't that dup2() to reset is failing because I have other functions in my larger program implementation that reset both stdin and stdout in the exact same manner, and are able to retrieve input from getline() following this.

Below is the issue that I'm having boiled down to a small segment.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char ** argv){

    char *input = NULL;
    size_t len = 0;
    int init; 
    int fd;

    getline(&input, &len, stdin);
    input = strtok(input, "\n");

    if((fd = open(input, O_RDONLY)) == -1){
        printf("error opening file\n");
    }
    if((init = dup(STDIN_FILENO)) == -1){
        printf("error duping initial stdin\n");
    }

    if(dup2(fd, STDIN_FILENO) == -1){
       printf("error duping fd\n");
    }
    close(fd);

    while(getline(&input, &len, stdin) != -1){
        printf("%s\n", input);
    }

    close(0);

    if(dup2(init, STDIN_FILENO) == -1){
       printf("error!\n");
    }

    getline(&input, &len, stdin);
    printf("%s\n", input);

    return 0;
}

This is the contents of the file the text file that I have been passing the program:

cd ..
echo 3207
touch test.txt
ls -la | grep test
cat < test.txt > out.txt
ls -l >> test.txt

It should be reading in input from the keyboard after printing these lines, but it simply prints the last line again and exits. Any advice is appreciated!

  • Are you familiar with buffering? – Joseph Sible-Reinstate Monica Mar 20 '21 at 23:36
  • I think you've got a few too many/misplaced `dup` calls. After the [last] `dup2`, the `stdin` _stream_ does _not_ know that you've done this, so it will have _stale_ data in the stream's buffer. You may need (e.g.) `rewind(stdin)`. But, for a shell impl, I'd avoid intermixing them. For a subshell [after a `fork`] you _don't_ want to do a `getline`, you just want to set up the units and exec something. I've posted some shells on SO, see: https://stackoverflow.com/questions/52823093/fd-leak-custom-shell/52825582#52825582 and https://stackoverflow.com/a/35570162/5382650 and see the pastebin link – Craig Estey Mar 21 '21 at 00:21
  • Wow, thank you so much Craig! This was super helpful and I was able to fix my problem - have a great night :) – bashful_creature Mar 21 '21 at 00:52
  • regarding: `if((fd = open(input, O_RDONLY)) == -1){ printf("error opening file\n"); }` 1) error messages should be output to `stderr`, not `stdout`. Suggest using `perror()` as that will output (to stderr) both the error message and the text reason the system thinks the error occurred. 2) when this error occurs, do NOT continue to execute the code, as if everything is OK – user3629249 Mar 21 '21 at 15:49

0 Answers0