1 /*
2 Copyright (C) 2019-2021, Dirk Krause
3 SPDX-License-Identifier: BSD-3-Clause
4 */
5 
6 /*
7 	WARNING: This file was generated by the dkct program (see
8 	http://dktools.sourceforge.net/ for details).
9 	Changes you make here will be lost if dkct is run again!
10 	You should modify the original source and run dkct on it.
11 	Original source: dk4dmt.ctr
12 */
13 
14 #ifndef DK4DMT_H_INCLUDED
15 /** Avoid multiple inclusions. */
16 #define DK4DMT_H_INCLUDED 1
17 
18 
19 /**	@file	dk4dmt.h	Daemon tool functions.
20 
21 The functions in this module can be used to program standing daemons.
22 Three processes are involved in a standing daemon:
23 
24 * master process, originally started,
25 * intermediate process, forked by master, decouples from terminal and
26 * daemon process, forked by intermediate process.
27 
28 When a standing daemon is started by a systemd service unit, the master
29 process must not exit before the daemon process has created the PID file.
30 
31 If you plan to give up root privileges in the child processes
32 (use setgid() and setuid() to change effective user and group),
33 do not use /var/run/<i>program</i>.pid as PID file name, better
34 use /var/run/<i>program</i>/<i>program</i>.pid instead and make
35 sure to set ownership and group on /var/run/<i>program</i>
36 to the unprivileged user and group used by the child process.
37 User and group need write permission to the directory, so the unprivileged
38 child process can remove the PID file when exiting.
39 
40 The general usage structure looks like this:
41 
42 @code
43 #define	PROGRAM_NAME "my-new-service"
44 const char program_name[] = {
45 	PROGRAM_NAME
46 };
47 const char pid_file_name[] = {
48 	"/run/" PROGRAM_NAME "/" PROGRAM_NAME ".pid"
49 };
50 dk4dmt_t	dmt;
51 
52 ...
53 
54 pid_t	cpid;
55 dk4dmt_init(&dmt);
56 if (0 != read_configuration_file()) {
57 	dk4dmt_set_program(&dmt, program_name);
58 	dk4dmt_set_pidfile(&dmt, pid_file_name);
59 	dk4dmt_set_syslog_feature(&dmt, syslog_feature);
60 	if (0 != dk4dmt_parent_before_fork(&dmt)) {
61 		cpid = fork();
62 		if ((pid_t)0 == cpid) {
63 			if (0 != dk4dmt_intermediate_before_fork(&dmt)) {
64 				cpid = fork();
65 				if ((pid_t)0 == cpid) {
66 					if (0 != dk4dmt_daemon_start(&dmt)) {
67 						do_the_service();
68 					}
69 					dk4dmt_daemon_end(&dmt);
70 				}
71 				else {
72 					if ((pid_t)(-1) != cpid) {
73 						dk4dmt_intermediate_after_fork(&dmt);
74 					}
75 					else {
76 						dk4dmt_intermediate_fork_failed(&dmt);
77 					}
78 				}
79 			}
80 		}
81 		else {
82 			if ((pid_t)(-1) != cpid) {
83 				dk4dmt_parent_after_fork(&dmt);
84 			}
85 			else {
86 				dk4dmt_parent_fork_failed(&dmt);
87 			}
88 		}
89 	}
90 }
91 else {
92 	dk4dmt_error_config(&dmt);
93 }
94 exval = dk4dmt_get_exit_status(&dmt);
95 exit(exval);
96 @endcode
97 
98 */
99 
100 #ifndef	DK4CONF_H_INCLUDED
101 #if DK4_BUILDING_DKTOOLS4
102 #include "dk4conf.h"
103 #else
104 #include <dktools-4/dk4conf.h>
105 #endif
106 #endif
107 
108 
109 /**	Data collection for daemon.
110 */
111 typedef struct {
112 	char	const	*prgname;	/**< Program name. */
113 	char	const	*pidfile;	/**< PID file name. */
114 	int				 pfd[2];	/**< Pipe file descriptors. */
115 	int				 logstderr;	/**< Flag: Logging to stderr allowed. */
116 	int				 slf;		/**< Syslog feature. */
117 	int				 exv;		/**< Exit status code to return. */
118 } dk4dmt_t;
119 
120 
121 
122 #ifdef	__cplusplus
123 extern "C" {
124 #endif
125 
126 /**	Initialize daemon tool structure.
127 	@param	pdmt	Daemon tool structure to initialize.
128 */
129 
130 void
131 dk4dmt_init(dk4dmt_t *pdmt);
132 
133 
134 /**	Set program name for daemon tool structure.
135 	The function does not create a copy of the program name,
136 	it keeps the original pointer in the structure.
137 	So the progname buffer must exist and contain data as long as
138 	the structure is used.
139 	@param	pdmt		Daemon tool structure to set up.
140 	@param	progname	Program name.
141 */
142 
143 void
144 dk4dmt_set_program(dk4dmt_t *pdmt, const char *progname);
145 
146 
147 /**	Set PID file name for daemon tool structure.
148 	The function does not create a copy of the file name, it keeps the original
149 	pointer in the structure.
150 	So the pidfile buffer must exist and contain data as long as
151 	the structure is used.
152 	@param	pdmt		Daemon tool structure to set up.
153 	@param	pidfile		PID file name.
154 */
155 
156 void
157 dk4dmt_set_pidfile(dk4dmt_t *pdmt, const char *pidfile);
158 
159 
160 /**	Enable or disable logging to stderr for daemon tool structure.
161 	@param	pdmt		Daemon tool structure to set up.
162 	@param	flag		Allow or deny logging to stderr.
163 */
164 
165 void
166 dk4dmt_set_log_stderr(dk4dmt_t *pdmt, int flag);
167 
168 
169 /**	Set syslog feature for daemon tool structure.
170 	@param	pdmt		Daemon tool structure to set up.
171 	@param	feat		Syslog feature to use.
172 */
173 
174 void
175 dk4dmt_set_syslog_feature(dk4dmt_t *pdmt, int feat);
176 
177 
178 /**	Process initialization before first fork attempt.
179 	Open pipe for communication from daemon to parent.
180 	@param	pdmt		Daemon tool structure to use.
181 	@return	1 on success, 0 on error.
182 */
183 
184 int
185 dk4dmt_parent_before_fork(dk4dmt_t *pdmt);
186 
187 
188 /**	Wait for startup completion notification in parent process.
189 	Close write head, read exit status, close read head.
190 	@param	pdmt		Daemon tool structure to use.
191 */
192 
193 void
194 dk4dmt_parent_after_fork(dk4dmt_t *pdmt);
195 
196 
197 /**	React on failed fork attempt in parent process.
198 	Close both pipe heads.
199 	@param	pdmt		Daemon tool structure to use.
200 */
201 
202 void
203 dk4dmt_parent_fork_failed(dk4dmt_t *pdmt);
204 
205 
206 /**	Prepare for second fork attempt in intermediate process.
207 	Close read head.
208 	On error write exit status code and close write pipe head.
209 	@param	pdmt		Daemon tool structure to use.
210 	@return	1 on success, 0 on error.
211 */
212 
213 int
214 dk4dmt_intermediate_before_fork(dk4dmt_t *pdmt);
215 
216 
217 /**	Clean up in intermediate process after forking the daemon.
218 	Close write pipe head.
219 	@param	pdmt		Daemon tool structure to use.
220 */
221 
222 void
223 dk4dmt_intermediate_after_fork(dk4dmt_t *pdmt);
224 
225 
226 /**	React on failed fork attempt in intermediate process.
227 	Write exit status code and close write pipe head.
228 	@param	pdmt		Daemon tool structure to use.
229 */
230 
231 void
232 dk4dmt_intermediate_fork_failed(dk4dmt_t *pdmt);
233 
234 
235 /**	Create PID file and notify main process to exit.
236 	Write exit status and close write pipe head.
237 	@param	pdmt	Daemon tool structure to use.
238 */
239 
240 int
241 dk4dmt_daemon_start(dk4dmt_t *pdmt);
242 
243 
244 /**	Clean up daemon structure before exiting daemon process (remove PID file).
245 	@param	pdmt	Daemon tool structure to use.
246 */
247 
248 void
249 dk4dmt_daemon_end(dk4dmt_t *pdmt);
250 
251 
252 /**	Set exit code in daemon structure for failed system function.
253 	@param	pdmt	Daemon tool structure to use.
254 */
255 
256 void
257 dk4dmt_error_sysfct(dk4dmt_t *pdmt);
258 
259 
260 /**	Set exit code in daemon structure for failed signal process mask.
261 	@param	pdmt	Daemon tool structure to use.
262 */
263 
264 void
265 dk4dmt_error_sigprocmask(dk4dmt_t *pdmt);
266 
267 
268 /**	Set exit code in daemon structure to indicate missing signal functionality.
269 	@param	pdmt	Daemon tool structure to use.
270 */
271 
272 void
273 dk4dmt_error_no_signal_function(dk4dmt_t *pdmt);
274 
275 
276 /**	Set exit code in daemon structure to indicate PID file exists.
277 	@param	pdmt	Daemon tool structure to use.
278 */
279 
280 void
281 dk4dmt_error_pid_file_exists(dk4dmt_t *pdmt);
282 
283 
284 /**	Set exit code in daemon structure to indicate PID file not configured.
285 	@param	pdmt	Daemon tool structure to use.
286 */
287 
288 void
289 dk4dmt_error_pid_file_name_missing(dk4dmt_t *pdmt);
290 
291 
292 /**	Set exit code in daemon structure to indicate write PID file failed.
293 	@param	pdmt	Daemon tool structure to use.
294 */
295 
296 void
297 dk4dmt_error_write_pid_file(dk4dmt_t *pdmt);
298 
299 /**	Set exit code in daemon structure to indicate pipe was not opened (bug).
300 	@param	pdmt	Daemon tool structure to use.
301 */
302 
303 void
304 dk4dmt_error_pipe_not_open(dk4dmt_t *pdmt);
305 
306 
307 /**	Set exit code in daemon structure to indicate reading from pipe failed.
308 	@param	pdmt	Daemon tool structure to use.
309 */
310 
311 void
312 dk4dmt_error_pipe_read_failed(dk4dmt_t *pdmt);
313 
314 
315 /**	Set exit code in daemon structure to indicate fork failed.
316 	@param	pdmt	Daemon tool structure to use.
317 */
318 
319 void
320 dk4dmt_error_fork_failed(dk4dmt_t *pdmt);
321 
322 
323 /**	Set exit code in daemon structure to indicate setsid failed.
324 	@param	pdmt	Daemon tool structure to use.
325 */
326 
327 void
328 dk4dmt_error_setsid(dk4dmt_t *pdmt);
329 
330 
331 /**	Set exit code in daemon structure to indicate dup2 failed.
332 	@param	pdmt	Daemon tool structure to use.
333 */
334 
335 void
336 dk4dmt_error_dup2_failed(dk4dmt_t *pdmt);
337 
338 
339 /**	Set exit code in daemon structure to indicate reading /dev/null failed.
340 	@param	pdmt	Daemon tool structure to use.
341 */
342 
343 void
344 dk4dmt_error_failed_read_dev_null(dk4dmt_t *pdmt);
345 
346 
347 /**	Set exit code in daemon structure to indicate writing /dev/null failed.
348 	@param	pdmt	Daemon tool structure to use.
349 */
350 
351 void
352 dk4dmt_error_failed_write_dev_null(dk4dmt_t *pdmt);
353 
354 
355 /**	Set exit code in daemon structure to indicate chdir to / failed.
356 	@param	pdmt	Daemon tool structure to use.
357 */
358 
359 void
360 dk4dmt_error_failed_chdir_root(dk4dmt_t *pdmt);
361 
362 
363 /**	Set exit code in daemon structure for failed signal set cleanup.
364 	@param	pdmt	Daemon tool structure to use.
365 */
366 
367 void
368 dk4dmt_error_sigemptyset(dk4dmt_t *pdmt);
369 
370 
371 /**	Set exit code in daemon structure for unusable configuration.
372 	@param	pdmt	Daemon tool structure to use.
373 */
374 
375 void
376 dk4dmt_error_config(dk4dmt_t *pdmt);
377 
378 
379 /**	Set exit code in daemon structure to indicate wrong call arguments.
380 	@param	pdmt	Daemon tool structure to use.
381 */
382 
383 void
384 dk4dmt_error_usage(dk4dmt_t *pdmt);
385 
386 
387 /**	Indicate success.
388 	@param	pdmt	Daemon tool structure to use.
389 */
390 void
391 dk4dmt_success(dk4dmt_t *pdmt);
392 
393 
394 /**	Retrieve exit status code.
395 	@param	pdmt	Daemon tool structure to use.
396 	@return	Exit status code to return.
397 */
398 
399 int
400 dk4dmt_get_exit_status(dk4dmt_t *pdmt);
401 
402 #ifdef	__cplusplus
403 }
404 #endif
405 
406 
407 #endif
408