aboutsummaryrefslogtreecommitdiffstats
path: root/console.c
blob: 208a691a2dd9685f70bcf148336dfa9a3feae862 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/*
 * console.c
 *
 * Manage attach/detach of a text console for stdin, stdout, stderr
 */

#include "console.h"

#ifndef O_TEXT
#define O_TEXT 0
#endif

static int redirect_stdio(const char *in, const char *out)
{
    int err = 0;
    int infd = -1;
    int outfd = -1;

    fflush(NULL);

    infd = open(in, O_RDWR | O_TEXT);
    if (infd >= 0) {
        if (!out)
            outfd = infd;
    } else {
        infd = open(in, O_RDONLY | O_TEXT);
    }

    if (infd < 0) {
        err = -1;
    } else {
        dup2(infd, STDIN_FILENO);
    }

    if (outfd < 0) {
        out = out ? out : in;
        outfd = open(out, O_RDWR | O_TEXT);
        if (outfd < 0)
            outfd = open(out, O_WRONLY | O_TEXT);
    }

    if (outfd < 0) {
        err = -1;
    } else {
        dup2(outfd, STDOUT_FILENO);
        dup2(outfd, STDERR_FILENO);
    }

    if (infd > STDERR_FILENO)
        close(infd);

    if (outfd != infd && outfd > STDERR_FILENO)
        close(outfd);

    return err;
}

#ifdef __WIN32__

void detach_console(void)
{
    redirect_stdio("\\Device\\Null", NULL);
    FreeConsole();
}

#else /* not __WIN32__ */

#ifndef _PATH_DEVNULL
#define _PATH_DEVNULL "/dev/null"
#endif

#ifndef HAVE_SETSID
#define setsid() ((void)0)
#endif

void detach_console(void)
{
    pid_t pid;

    redirect_stdio(_PATH_DEVNULL, NULL);

    pid = fork();

    if (pid < 0)
        return;
    else if (pid > 0)
        _exit(0);

    setsid();
}

#endif