53 {
54 if (std::filesystem::exists(pidFileName)) {
55 throw DaemonFailure("Pid file '" + pidFileName + "' exists. Daemon already running?");
56 }
57 errno = 0;
58
59
60 pid_t pid = fork();
61 if (pid < 0) {
62
63 throw DaemonError("First fork()");
64 }
65 if (pid > 0) {
66
67 throw DaemonSignaled("Lead new session", pid);
68 }
69
70 if (setsid() < 0) {
71
72 throw DaemonError("setsid()");
73 }
74
75 if (
signal(SIGHUP, SIG_IGN) == SIG_ERR) {
76
77 throw DaemonError("signal()");
78 }
79
80
81 pid = fork();
82 if (pid < 0) {
83
84 throw DaemonError("Second fork()");
85 }
86 if (pid > 0) {
87
88 std::ofstream pidFile(pidFileName, std::ofstream::out);
89
90 if (!pidFile.good()) {
91 kill(pid, SIGTERM);
92 throw DaemonError("Writing pid file '" + pidFileName);
93 }
94 pidFile << pid << std::endl;
95 pidFile.close();
96
97 throw DaemonSignaled("Drop session lead", pid);
98 }
99
100 struct passwd* pw = nullptr;
101 struct group* gr = nullptr;
102
103 if (((void) (errno = 0), gr = getgrnam(groupName.c_str())) == nullptr) {
104 if (errno != 0) {
105 throw DaemonError("getgrnam()");
106 }
107 throw DaemonFailure("getgrname() group not existing");
108 }
109 if (setegid(gr->gr_gid) != 0) {
110 throw DaemonError("setegid()");
111 }
112 if (((void) (errno = 0), (pw = getpwnam(userName.c_str())) == nullptr)) {
113 if (errno != 0) {
114 throw DaemonError("getpwnam()");
115 }
116 throw DaemonFailure("getpwnam() user not existing");
117 }
118 if (seteuid(pw->pw_uid) != 0) {
119 throw DaemonError("seteuid()");
120 }
121 umask(0);
122 chdir("/");
123
125 close(STDOUT_FILENO);
126 close(STDERR_FILENO);
127
128 if (std::freopen("/dev/null", "r", stdin) == nullptr) {
129 }
130 if (std::freopen("/dev/null", "w+", stdout) == nullptr) {
131 }
132 if (std::freopen("/dev/null", "w+", stderr) == nullptr) {
133 }
134 }
sighandler_t signal(int sig, sighandler_t handler)