C - stdout redirection after expanding child from parent

I am writing a program to execute another program as a forked process and redirecting it to a file or / dev / null on demand.

Currently, I have forked and executed an external program using execvp (). Then it redirected stdout from the stream created before the fork, as the forked process inherits the parent file descriptor table, which allows me to redirect after focus.

But I can first redirect stdout to the desired file, and both parents and child stdouts will be redirected. However, if I try to redirect it again to another file, only the parent stdout will be redirected, the child stdout will remain the same.

Here's the code without all the error checking bits.

struct params {
    const char *p;
    int fd;
    int wait;
};

#define EXIT_NOEXEC 126
#define EXIT_NOTFOUND   127
#define EXIT_MISC   127

static void dofile(struct params* st);
void dupit(const char *p, struct params* st);
void* reload_config(void* para);

int
main(int argc, char *argv[]) {
    int exit_status, prog_status;
    struct params init;
    pid_t prog_pid;


    dofile(&init);

    prog_pid = fork();
    if (prog_pid == 0) {
        execvp(*argv, argv);
        exit_status = (errno == ENOENT) ? EXIT_NOTFOUND : EXIT_NOEXEC;
        err(exit_status, "%s", argv[0]);
        exit(EXIT_FAILURE);
    } else {
        while (wait(&prog_status) != prog_pid);
        return prog_status;
    }
}

static void dofile(struct params* st) {
    const char *p
    p = out.txt;
    dupit(p, st);

}


void dupit(const char *p, struct params* st) {
    pthread_t tid;
    st->wait = 0;
    int err = pthread_create(&(tid), NULL, &reload_config, st);
    if (err != 0) {
        printf("\ncan't create thread :[%s]", strerror(err));
        exit(1);
    } else {
        while (st->wait == 0) {
            sleep(1)
        }
    }
}

void* reload_config(void* para) {
    struct params *passed = (struct params *) para;
    int pre_config = 3; 
    int cur_config = 1; 
    int saved_stdout = dup(STDOUT_FILENO);
    char infile[5];
    int devNull = open("/dev/null", O_WRONLY);
    int file = open("out.txt", O_WRONLY);
    FILE *config;
    config = fopen("config.txt", "r");
    if (access("config.txt", F_OK) != -1) {
        while (1) {
            fgets(infile, 5, config);
            fclose(config);
            cur_config = infile[0] - '0';
            printf("output from thread, current config = %d\n", cur_config);
            if (pre_config != cur_config) {
                if (cur_config == 1) {
                    if (dup2(file, STDOUT_FILENO) == -1) {
                        err(EXIT_MISC, NULL);
                    }
                } else {
                    dup2(devNull, STDOUT_FILENO);
                }
                pre_config = cur_config;
            }
            if (passed->wait==0) {
                passed->wait = 1;
            }
            sleep(1);
        }
    } else {
        if (dup2(passed->fd, STDOUT_FILENO) == -1) {
            err(EXIT_MISC, NULL);
        }
    }
}

, , , , , . .

stdout .

+4
1

, . , , , . 1 stdout . . stdout ( printf) 1 . IPC, pipe , .

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

int main(int argc, char **argv)
{  
    pid_t pid;
    const char *file1 = "file1.txt";
    const char *file2 = "file2.txt";
    int pipefd[2];
    int fd;
    int rval;

    fd = open(file1, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);
    if (fd == -1) {
        perror("file1 open");
        exit(-1);
    }

    /*
     * This pipe will be used by parent process to tell child which file
     * to redirect to.
     */
    rval = pipe2(pipefd, O_NONBLOCK);
    if (fd == -1) {
        perror("pipe");
        exit(-1);
    }

    /* Redirect stdout to the file opened before the fork. */
    dup2(fd, STDOUT_FILENO);

    pid = fork();

    if (pid == -1) {
        perror("fork");
        exit(-1);
    } else if (pid == 0) {
        /* Child process. */
        int ix;
        char redirect_file[100];

        close(pipefd[1]);

        for (ix = 0; ix < 10; ix++) {

            printf("%d\n", ix);
            sleep(1);

            rval = read(pipefd[0], redirect_file, sizeof(redirect_file));
            if (rval > 0) {
                /*
                 * Parent process has written a filename to the pipe.
                 */ 
                fd = open(redirect_file, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);
                if (fd == -1) {
                    perror("file2 open");
                    exit(-1);
                }

                /* Ensure previous output has been written to current file. */
                fflush(stdout);

                /* Change redirect now. */
                dup2(fd, STDOUT_FILENO);
            }
        }
    } else {
        /* Parent process. */
        close(pipefd[0]);

        /* Wait a little and then tell child to change redirect file. */
        sleep(5);
        write(pipefd[1], file2, strlen(file2) + 1);

        wait();
    }
}

, , 1 ( ), 2 ( ).

$ cat file1.txt 
0
1
2
3
4
$ cat file2.txt 
5
6
7
8
9

. dup fork. , , fork . - fork, dup , , exec. dup fork, , ( , ).

+1

Source: https://habr.com/ru/post/1620667/


All Articles