File: daemonise.c

package info (click to toggle)
ekeyd 1.1.5-8
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 812 kB
  • sloc: ansic: 5,259; sh: 333; makefile: 203; perl: 150; xml: 17
file content (113 lines) | stat: -rw-r--r-- 2,271 bytes parent folder | download | duplicates (4)
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/* daemon/daemonise.c
 *
 * Daemonisation support code
 *
 * Copyright 2009-2011 Simtec Electronics
 *
 * For licence terms refer to the COPYING file.
 */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <stdbool.h>

#include "daemonise.h"

/* exported interface documented in daemonise.h */
void
do_daemonise(const char *pidfilename, bool close_all_fd)
{
    int fd;
    int pid;
    FILE *pidfile;
    int pipefds[2];
    int fdlimit;
    int cfd;

    if (pipe(pipefds) == -1) {
	perror("pipe");
	exit(1);
    }

    switch ((pid = fork())) {
    case 0:
        /* Child */
        break; /* logic below */

    case -1:
        /* Error */
        perror("fork");
        exit(1);
        break;

    default:
        /* Parent */
        close(pipefds[1]);
        /* wait until child closes pipe */
        if (read(pipefds[0], &pid, 1) < 0)
            perror("read");
        exit(0);
    }

    /* Make stdin/out/err all be /dev/null */
    fd = open("/dev/null", O_RDWR);
    if (fd == -1) {
	perror("/dev/null open");
	exit(1);
    }

    dup2(fd, 0);
    dup2(fd, 1);
    dup2(fd, 2);
    close(fd);
    if (chdir("/") == -1) {
	perror("chdir");
	exit(1);
    }

    if (close_all_fd) {
        /* ensure any other fd are closed */
        fdlimit = sysconf(_SC_OPEN_MAX);
        for (cfd = 3; cfd < fdlimit ; cfd++) {
            if ((cfd != pipefds[0]) && 
                (cfd != pipefds[1])) {
                close(cfd);
            }
        }
    }

    /* Ensure our process group is better */
    setsid();
    setpgid(0, 0);

    /* Second fork() ensures we can never regain a controlling tty */
    switch ((pid = fork())) {
    case -1:
        /* Error */
        exit(1);

    case 0:
        /* Child */
        close(pipefds[0]);
        close(pipefds[1]); /* Signals outer-parent that we're done */
        break;

    default:
        /* Parent */
        if (pidfilename != NULL) {
            pidfile = fopen(pidfilename, "w");
            if (pidfile == NULL) {
                perror("open");
                kill(pid, SIGQUIT);
                exit(2);
            }
            fprintf(pidfile, "%d\n", pid);
            fclose(pidfile);
        }
        exit(0);
    }

}