Dima
Dima

Reputation: 83

How to redirect stderr and stdout to the same file

I have a task to make both stderr and stdout to print to a file called "log.out". I"m not allowed to delete code lines, only to add them. The stdout part was easy, I have just added close(1); and now it is working. But I have already spend a couple for hours trying to learn how to use the whole dup/dup1/dup2 technic but I"m just not able to make it work even after reading a lot about the subject in the internet. It would be really nice if someone will show me what lines of code I need to add to make it work, and explain me how it works. Thanks!

#include<stdio.h>
#include<stdlib.h>
#include <unistd.h>         // for fork, sleep etc.
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h> 
#include <fcntl.h>   

void fork_son(char*, int);
void do_son();
int open_file(char*);

int
main()
{
    fork_son("1st", 0);
    fork_son("2nd", 1);
    exit(0);
}

void fork_son(char* which, int need_file)
{
    int pid;
    int status;
    if (need_file)
    {
                close(1); //close stdout

        open_file("log.out");
    }
    // close and open files before forking

    pid = fork();
    if (pid <0) 
    {
        fprintf(stderr,"process %d, Fork Failed... Exiting\n", getpid());
        exit(1);
    }
    if (pid == 0)
        do_son(which);
    else
    {
        printf("waiting for %s son...", which);
        wait(&status);
        printf("%s son exited!\n", which);
    }
    return;
}   

void do_son(char* which) 
{
    fprintf(stdout,"Hello from %s son!\n", which);
    fprintf(stderr,"%s son: I'm going to exit\n", which);
    exit(0);
}   

int open_file(char* name)
{
    int fd;
    fd = open(name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
    // check if open succeeded
    if (fd <0) 
    {
        fprintf(stderr, "ERROR: open \"%s\" failed (%d). Exiting\n", name, fd);
        exit(2);
    }
    // if (fd != 1) 
    // {
        // fprintf(stderr,"ERROR: open \"%s\" - fd is %d (expected 1). Exiting\n", name, fd);
        // exit(3);
    // }
    printf("opened file %s, file descriptor is: %d\n",name, fd);
    return(fd);
}

Upvotes: 3

Views: 1112

Answers (1)

Tony Tannous
Tony Tannous

Reputation: 14866

The way open works, it searches for free entry in file descriptor table. Where entries 0, 1 and 2 are reserved for stdin, stdout and stderr respectively.

stdin  - 0
stdout - 1
stderr - 2

If you want to redirect stdout and stderr to log.out you could simply do the following:

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

int main()
{
    int fd = - 1;
    fd = open("log.out", O_RDWR | O_CREAT); 

    dup2(fd, 1); // redirects stdout to log.out
    dup2(fd, 2); // redirects stderr to log.out

    /* Print to stderr and to stdout */
    fprintf(stdout, "%s", "Hello world\n");     
    fprintf(stderr, "%s", "Stack overflow!\n");
    return 0;
}

If you care about order, a call to fflush should follow fprintf as redirecting stdout to a file will not flush buffer on newlines.

Upvotes: 3

Related Questions