Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6738539
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 26, 20262026-05-26T11:22:51+00:00 2026-05-26T11:22:51+00:00

I have to modify a simple shell I wrote for a previous homework assignment

  • 0

I have to modify a simple shell I wrote for a previous homework assignment to handle I/O redirection and I’m having trouble getting the pipes to work. It seems that when I write and read to stdout and from stdin after duplicating the file descriptors in the separates processes, the pipe works, but if I use anything like printf, fprintf, gets, fgets, etc to try and see if the output is showing up in the pipe, it goes to the console even though the file descriptor for stdin and stdout clearly is a copy of the pipe (I don’t know if that’s the correct way to phrase that, but the point is clear I think).

I am 99.9% sure that I am doing everything as it should be at least in plain C — such as closing all the file descriptors appropriately after the dup() — and file I/O works fine, so this seems like an issue of a detail that I am not aware of and cannot find any information on. I’ve spent most of the day trying different things and the past few hours googling trying to figure out if I could redirect cin and cout to the pipe to see if that would fix it, but it seems like it’s more trouble than it’s worth at this point.

Should this work just by redirecting stdin and stdout since cin and cout are supposed to be sync’d with stdio? I thought it should, especially since the commands are probably written in C so they would use stdio, I would think. However, if I try a command like “cat [file1] [file2] | sort”, it prints the result of cat [file1] [file2] to the command line, and the sort doesn’t get any input so it has no output. It’s also clear that cout and cin are not affected by the dup() either, so I put two and two together and came to this conclusion
Here is a somewhat shortened version of my code minus all the error checking and things like that, which I am confident I am handling well. I can post the full code if it come to it, but it’s a lot so I’ll start with this.

I rewrote the function so that the parent forks off a child for each command and connects them with pipes as necessary and then waits for the child processes to die. Again, write and read on the file descriptors 0 and 1 work (i.e. write to and reads from the pipe), stdio on the FILE pointers stdin and stdout do not work (do not write to pipe).

Thanks a lot, this has been killing me…

UPDATE: I wasn’t changing the string cmd for each of the different commands so it didn’t appear to work because the pipe just went to the same command so the final output was the same… Sorry for the dumbness, but thanks because I found the problem with strace.

int call_execv( string cmd, vector<string> &argv, int argc,
    vector<int> &redirect)
{
    int result = 0, pid, /* some other declarations */;
    bool file_in, file_out, pipe_in, pipe_out;
    queue<int*> pipes; // never has more than 2 pipes

    // parse, fork, exec, & loop if there's a pipe until no more pipes
    do
    {
        /* some declarations for variables used in parsing */
        file_in = file_out = pipe_in = pipe_out = false;

        // parse the next command and set some flags
        while( /* there's more redirection */ )
        {
            string symbol = /* next redirection symbol */

            if( symbol == ">" )
            {
                /* set flags, get filename, etc */
            }   
            else if( symbol == "<" )
            {
                /* set flags, get filename, etc */
            }
            else if( pipe_out = (symbol == "|") )
            {
                    /* set flags, and... */
                int tempPipes[2];               
                pipes.push( pipe(tempPipes) );
                break;
            }
        }

        /* ... set some more flags ... */

        // fork child
        pid = fork();
        if( pid == 0 )  // child
        {
            /* if pipe_in and pipe_out set, there are two pipes in queue. 
            the old pipes read  is dup'd to stdin, and the new pipes
            write is dup'd to stdout, other two FD's are closed */

            /* if only pipe_in or pipe_out, there is one pipe in queue.
            the unused end is closed in whichever if statement evaluates */

            /* if neither pipe_in or pipe_out is set, no pipe in queue */

            // redirect stdout
            if( pipe_out ){
                // close newest pipes read end
                close( pipes.back()[P_READ] );

                // dup the newest pipes write end
                dup2( pipes.back()[P_WRITE], STDOUT_FILENO );

                // close newest pipes write end
                close( pipes.back()[P_WRITE] );
            }
            else if( file_out ) 
                freopen(outfile.c_str(), "w", stdout);

            // redirect stdin
            if( pipe_in ){
                close( pipes.front()[P_WRITE] );
                dup2( pipes.front()[P_READ], STDIN_FILENO );
                close( pipes.front()[P_READ] );
            }
            else if ( file_in ) 
                freopen(infile.c_str(), "r", stdin);


            // create argument list and exec
            char **arglist = make_arglist( argv, start, end );
            execv( cmd.c_str(), arglist );

            cout << "Execution failed." << endl;    
            exit(-1); // this only executes is execv fails

        }   // end child

        /* close the newest pipes write end because child is writing to it.
           the older pipes write end is closed already */
        if( pipe_out ) 
            close( pipes.back()[P_WRITE] );

        // remove pipes that have been read from front of queue
        if( init_count > 0 )    
        {
            close( pipes.front()[P_READ] ); // close FD first
            pipes.pop();                    // pop from queue
        }   

    } while ( pipe_out );

    // wait for each child process to die

    return result;
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-26T11:22:52+00:00Added an answer on May 26, 2026 at 11:22 am

    Whatever the problem, you are not checking any return values. How do you know if the pipe() or the dup2() command succeeded? Have you verified that stdout and stdin really point to the pipe right before execv? Does execv keep the filedescriptors you give it? Not sure, here is the corresponding paragraph from the execve documentation:

    • By default, file descriptors remain open across an execve(). File descriptors that are marked close-on-exec are closed; see the description of FD_CLOEXEC in fcntl(2). (If a
      file descriptor is closed, this will cause the release of all record locks obtained on the underlying file by this process. See fcntl(2) for details.) POSIX.1-2001 says
      that if file descriptors 0, 1, and 2 would otherwise be closed after a successful execve(), and the process would gain privilege because the set-user_ID or set-group_ID per‐
      mission bit was set on the executed file, then the system may open an unspecified file for each of these file descriptors. As a general principle, no portable program,
      whether privileged or not, can assume that these three file descriptors will remain closed across an execve().

    You should add more debug output and see what really happens. Did you use strace -f (to follow children) on your program?

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Have people noticed that if you modify the source of a shell script, any
I have a simple animation which simply modify the position of a button: [UIView
I have a very simple HTML. Due to some limitations, I cannot modify the
For a university assignment, we have to modify the ext2 file system to store
I have a Windows shell script that opens an application. I'd like to modify
I have a requirement to modify a simple windows service written in win32 C
I have the following simple NodeJS script and want to modify it slightly.... var
I have a simple proxy source in C++. I'm trying to modify it to
I have a simple Chrome extension that uses the content script feature to modify
I've got an MS-Access database stored in a folder (yes, I have 'Modify' permissions

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.