aboutsummaryrefslogtreecommitdiff
path: root/src/detach-bsd.c
blob: ee235b3501f5493cc38f1066406ecc166a753bc8 (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
/* direvent - directory content watcher daemon
   Copyright (C) 2012-2014 Sergey Poznyakoff

   Direvent is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 3 of the License, or (at your
   option) any later version.

   Direvent is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License along
   with direvent. If not, see <http://www.gnu.org/licenses/>. */

/* "Early-init" detach() for BSD systems. It uses rfork instead of fork
   to ensure the event queue is inherited by the child process.  According
   to the kqueue(2) manpage:

   The kqueue() system call creates a new kernel event queue and returns a
   descriptor.  The queue is not inherited by a child created with fork(2).
   However, if rfork(2) is called without the RFFDG flag, then the descrip-
   tor table is shared, which will allow sharing of the kqueue between two
   processes.
*/	

#include "direvent.h"
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <stdlib.h>

#ifdef HAVE_PATHS_H
# include <paths.h>
#endif

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

int
detach(void (*init)())
{
	struct sigaction oldsa, sa;
	pid_t pid;
	int ec;

	init();
	
	sigemptyset(&sa.sa_mask);
	sa.sa_handler = SIG_IGN;
	sa.sa_flags = 0;

	if (sigaction(SIGHUP, &sa, &oldsa))
		return -1;

	switch (rfork(RFPROC)) {
	case -1:
		return -1;
	case 0:
		break;
	default:
		_exit(0);
	}

	pid = setsid();
	ec = errno;
	
	sigaction(SIGHUP, &oldsa, NULL);
	
	if (pid == -1) {
		errno = ec;
		return -1;
	}

	chdir("/");

	close(0);
	close(1);
	close(2);
	open(_PATH_DEVNULL, O_RDONLY);
	open(_PATH_DEVNULL, O_WRONLY);
	dup(1);

	return 0;
}
	
		

Return to:

Send suggestions and report system problems to the System administrator.