1/*
2 * Copyright 2007, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Axel Dörfler, axeld@pinc-software.de
7 */
8
9#include <fcntl.h>
10#include <stdlib.h>
11#include <signal.h>
12#include <unistd.h>
13
14
15static void
16restore_old_sighup(int result, struct sigaction *action)
17{
18	if (result != -1)
19		sigaction(SIGHUP, action, NULL);
20}
21
22
23int
24daemon(int noChangeDir, int noClose)
25{
26	struct sigaction oldAction, action;
27	int oldActionResult;
28	pid_t newGroup;
29	pid_t pid;
30
31	/* Ignore eventually send SIGHUPS on parent exit */
32	sigemptyset(&action.sa_mask);
33	action.sa_handler = SIG_IGN;
34	action.sa_flags = 0;
35	oldActionResult = sigaction(SIGHUP, &action, &oldAction);
36
37	pid = fork();
38	if (pid == -1) {
39		restore_old_sighup(oldActionResult, &oldAction);
40		return -1;
41	}
42	if (pid > 0) {
43		// we're the parent - let's exit
44		exit(0);
45	}
46
47	newGroup = setsid();
48	restore_old_sighup(oldActionResult, &oldAction);
49
50	if (newGroup == -1)
51		return -1;
52
53	if (!noChangeDir)
54		chdir("/");
55
56	if (!noClose) {
57		int fd = open("/dev/null", O_RDWR);
58		if (fd != -1) {
59			dup2(fd, STDIN_FILENO);
60			dup2(fd, STDOUT_FILENO);
61			dup2(fd, STDERR_FILENO);
62			if (fd > STDERR_FILENO)
63				close(fd);
64		}
65	}
66
67	return 0;
68}
69