75 {
76 if (std::filesystem::exists(pidFileName)) {
77 throw DaemonFailure("Pid file '" + pidFileName + "' exists. Daemon already running?");
78 }
79 errno = 0;
80
81
82 pid_t pid = fork();
83 if (pid < 0) {
84
85 throw DaemonError("First fork()");
86 }
87 if (pid > 0) {
88
89 throw DaemonSignaled("Lead new session", pid);
90 }
91
92 if (setsid() < 0) {
93
94 throw DaemonError("setsid()");
95 }
96
97 if (
signal(SIGHUP, SIG_IGN) == SIG_ERR) {
98
99 throw DaemonError("signal()");
100 }
101
102
103 pid = fork();
104 if (pid < 0) {
105
106 throw DaemonError("Second fork()");
107 }
108 if (pid > 0) {
109
110 std::ofstream pidFile(pidFileName, std::ofstream::out);
111
112 if (!pidFile.good()) {
113 kill(pid, SIGTERM);
114 throw DaemonError("Writing pid file '" + pidFileName);
115 }
116 pidFile << pid << std::endl;
117 pidFile.close();
118
119 throw DaemonSignaled("Drop session lead", pid);
120 }
121
122 struct passwd* pw = nullptr;
123 struct group* gr = nullptr;
124
125 if (((void) (errno = 0), gr = getgrnam(groupName.c_str())) == nullptr) {
126 if (errno != 0) {
127 throw DaemonError("getgrnam()");
128 }
129 throw DaemonFailure("getgrname() group not existing");
130 }
131 if (setegid(gr->gr_gid) != 0) {
132 throw DaemonError("setegid()");
133 }
134 if (((void) (errno = 0), (pw = getpwnam(userName.c_str())) == nullptr)) {
135 if (errno != 0) {
136 throw DaemonError("getpwnam()");
137 }
138 throw DaemonFailure("getpwnam() user not existing");
139 }
140 if (seteuid(pw->pw_uid) != 0) {
141 throw DaemonError("seteuid()");
142 }
143 umask(0);
144 chdir("/");
145
147 close(STDOUT_FILENO);
148 close(STDERR_FILENO);
149
150 if (std::freopen("/dev/null", "r", stdin) == nullptr) {
151 }
152 if (std::freopen("/dev/null", "w+", stdout) == nullptr) {
153 }
154 if (std::freopen("/dev/null", "w+", stderr) == nullptr) {
155 }
156 }
sighandler_t signal(int sig, sighandler_t handler)