0

I'm trying to create two child processes:

One child reads its input from a file, which is passed in as an argument, and writes output to the pipe.

The other child reads its output from the pipe and writes its output to a file, also passed in as an argument.

The parent sets up some of the file descriptors for the children and when the children are created they finish manipulating the descriptors to their needs.

However, I'm having an issue with setting up the file descriptors, specifically, when I try to close and dup the input file descriptor to take the place of stdin.

Here's all my code:

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

int main(int argc, char *argv[])
{
    //Open input file
    int fdin;
    fdin = open(argv[1], O_RDONLY);
    //Check if opening the file was successful
    if(fdin > 0)
    {
        //Open output file
        int fdout;
        //Create the output file and
        //check if the output file was created
        if((fdout = creat(argv[2], 0644)) > 0)
        {
            //Captures whether the dup's were successful
            int dup_in;
            int dup_out;

            //Close stdin so we can replace it with our input file
            close(0);
            //Attempt to put the input file at position 0
            //and check if the dup was successful
            if((dup_in = dup(fdin)) > 0)
            {
                //Close stdout so we can replace it with our output file
                close(1);

                //Attempt to put the output file at position 1
                //and check if the dup was successful
                if((dup_out = dup(fdout)) > 0)
                {
                    //Pipe success
                    int pipecreate;
                    //Pipe file descriptors
                    int pipe_fd[2];

                    //Make the pipe and check
                    //if it was successful
                    if((pipecreate = pipe(pipe_fd)) > 0)
                    {
                        //close unneeded file descriptors
                        close(fdin);
                        close(fdout);

                        //Process id for first child
                        int cpid1;
                        //Create first child process
                        cpid1 = fork();

                        //Process creation successful, child block
                        if(cpid1 == 0)
                        {
                            //Read pipe dup success
                            int rpipe_dup;
                            //close f_in
                            close(0);

                            rpipe_dup = dup(pipe_fd[0]);

                            //Dup successful
                            if(rpipe_dup > 0)
                            {
                                //close uneeded file descriptors
                                close(pipe_fd[0]);
                                close(pipe_fd[1]);

                                execl("count", "count", (char *) 0);

                                char readbuf[100] = {0};

                                read(2, readbuf, 100);
                            }
                            //Dup failed
                            else
                            {
                                fprintf(stderr, "Read pipe dup failed.\n");
                                exit(EXIT_FAILURE);
                            }
                        }
                        //Process creation successful, parent block
                        else if(cpid1 > 0)
                        {
                            //Process id for second child
                            int cpid2;
                            //Create second child process
                            cpid2 = fork();

                            //Process creation successful, child block
                            if(cpid2 == 0)
                            {
                                //Write pipe dup success
                                int wpipe_dup;
                                //close f_out
                                close(1);

                                wpipe_dup = dup(pipe_fd[1]);

                                //Dup successful
                                if(wpipe_dup > 0)
                                {
                                    //close uneeded file descriptors
                                    close(pipe_fd[0]);
                                    close(pipe_fd[1]);

                                    execl("convert", "convert", (char *) 0);

                                    char readbuf[100] = {0};

                                    write(1, readbuf, 100);
                                }
                                //Dup failed
                                else
                                {
                                    fprintf(stderr, "Write pipe dup failed.\n");
                                    exit(EXIT_FAILURE);
                                }
                            }
                            //Process creation successful, parent block
                            else if(cpid2 > 0)
                            {
                                //Close unneeded file descriptors
                                close(pipe_fd[0]);
                                close(pipe_fd[1]);

                                int pid;
                                int status;

                                pid = wait(&status);
                                pid = wait(&status);

                            }
                            //Dup failed
                            else
                            {
                                fprintf(stderr, "Error creating child process 2.\n");
                                exit(EXIT_FAILURE);
                            }
                        }
                        //Process creation unsuccessful
                        else
                        {
                            fprintf(stderr, "Error creating child process 1.\n");
                            exit(EXIT_FAILURE);
                        }
                    }
                    //Pipe creation failed
                    else
                    {
                        fprintf(stderr, "Error creating pipe.\n");
                        exit(EXIT_FAILURE);
                    }
                }
                //Dup'ing the output file descriptor failed
                else
                {
                    fprintf(stderr, "Error dup'ing out file descriptor.\n");
                    exit(EXIT_FAILURE);
                }
            }
            //Dup'ing the input file descriptor failed
            else
            {
                //fprintf(stderr, "Error dup'ing in file descriptor.\n
                perror("\nError dup'ing in file descriptor: ");
                exit(EXIT_FAILURE);
            }
        }
        //Creat failed
        else
        {
            fprintf(stderr, "Error creating out file.\n");
            exit(EXIT_FAILURE);
        }
    }
    //Opening input file failed
    else
    {
        fprintf(stderr, "Error opening in file.\n");
        exit(EXIT_FAILURE);
    }
}

I'm compiling and running this on MINIX3.

Here's how I run it, including program output:

cc fork.c
./a.out input.txt output.txt

Error dup'ing in file descriptor: : Undefined error: 0

Any help is greatly appreciated.

braab
  • 87
  • 2
  • 11
  • 1
    I found out why. dup returns the file descriptor number, which, in this case is 0. if((dup_in = dup(fdin)) > 0) should be if((dup_in >= dup(fdin)) > 0) – braab Sep 25 '14 at 01:13
  • If you have found the answer to your question, post that as the answer, not as a comment. – indiv Sep 25 '14 at 01:43

1 Answers1

0

I found out why.

dup returns the file descriptor number, which, in this case, is 0. if ((dup_in = dup(fdin)) > 0) should be if ((dup_in >= dup(fdin))).

Dimitar
  • 4,402
  • 4
  • 31
  • 47
braab
  • 87
  • 2
  • 11
  • Why do you have that `>0` there? why not just `if(dup_in >= dup(fdin)) `? – hyde Sep 26 '14 at 18:22
  • `dup_in = dup(fdin)` and `dup_in >= dup(fdin)` are obviously very different statements, and cannot remotely substitute for each other. In the latter case, the return value from `dup()` will not be assigned to `dup_in`, and will be lost. In addition, you'll be attempting to access the value of `dup_in` which, at that point, is uninitialized. Perhaps you mean `if ( (dup_in = dup(fdin)) >= 0 )`, or even better, `if ( (dup_in = dup(fdin)) != -1 )`. – Crowman Sep 26 '14 at 18:30
  • The >0 wasn't meant to be there, I forgot to remove it when I fixed it. Also, Paul, I did change it to if ( (dup_in = dup(fdin)) >= 0 ) – braab Sep 26 '14 at 18:45