I have the following C code which does "ls | tr a-z A-Z" but I don't know how to make the output go to file.txt. Do I need to create another pipe or fork thrice? Do I need to use open() function at all since I am saving the output to a file?
int main() {
pid_t child_pid_one, child_pid_two;
int pipe_fd[2]; /* pipe */
/* Before the fork, we need to create the pipe */ 
/* (otherwise no sharing of pipe) */
if (pipe(pipe_fd) < 0) {
  err(EX_OSERR, "pipe error");
}
if ((child_pid_one = fork()) < 0) {
  err(EX_OSERR, "fork error");
}
if (child_pid_one == 0)  { /* CHILD #1's code (ls code) */
  close(pipe_fd[0]); /* we don't need pipe's read end */
  /* Redirecting standard output to pipe write end */
  if (dup2(pipe_fd[1], STDOUT_FILENO) < 0) {
     err(EX_OSERR, "dup2 error");
  }
  execlp("/bin/ls", "/bin/ls", NULL);
  err(EX_OSERR, "exec error");
}  else { /* parent's code */
  /* Creating second child */
  if ((child_pid_two = fork()) < 0) {
     err(EX_OSERR, "fork error");
  } 
  if (child_pid_two == 0)  { /* CHILD #2's code (tr a-z A-Z) */
     close(pipe_fd[1]); /* we don't need pipe's write end */
     /* Redirecting standard input to pipe read end */
     if (dup2(pipe_fd[0], STDIN_FILENO) < 0) {
        err(EX_OSERR, "dup2 error");
     }
     execlp("/usr/bin/tr", "/usr/bin/tr","a-z","A-Z", NULL);
     err(EX_OSERR, "exec error");
  } else {
     /* Parent has no need for the pipe */
     close(pipe_fd[0]);
     close(pipe_fd[1]);
     /* Reaping each children */
     wait(NULL); 
     wait(NULL);
  }
 }
 return 0;
}
				
                        
Just redirect
STDOUT_FILENOof thetrprocess to a newly opened file: