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 /**	@file dk4dmt.c The dk4dmt module.
15 */
16 
17 
18 #include "dk4conf.h"
19 
20 #include <stdio.h>
21 
22 #if	DK4_HAVE_SYS_TYPES_H
23 #ifndef	SYS_TYPES_H_INCLUDED
24 #include <sys/types.h>
25 #define	SYS_TYPES_H_INCLUDED 1
26 #endif
27 #endif
28 
29 #if	DK4_HAVE_SYS_STAT_H
30 #ifndef	SYS_STAT_H_INCLUDED
31 #include <sys/stat.h>
32 #define	SYS_STAT_H_INCLUDED 1
33 #endif
34 #endif
35 
36 #if	DK4_HAVE_STDLIB_H
37 #ifndef	STDLIB_H_INCLUDED
38 #include <stdlib.h>
39 #define	STDLIB_H_INCLUDED 1
40 #endif
41 #endif
42 
43 #if	DK4_HAVE_UNISTD_H
44 #ifndef	UNISTD_H_INCLUDED
45 #include <unistd.h>
46 #define	UNISTD_H_INCLUDED 1
47 #endif
48 #endif
49 
50 #if	DK4_HAVE_FCNTL_H
51 #ifndef	FCNTL_H_INCLUDED
52 #include <fcntl.h>
53 #define	FCNTL_H_INCLUDED 1
54 #endif
55 #endif
56 
57 #if	DK4_HAVE_SIGNAL_H
58 #ifndef	SIGNAL_H_INCLUDED
59 #include <signal.h>
60 #define	SIGNAL_H_INCLUDED 1
61 #endif
62 #endif
63 
64 #if	DK4_HAVE_IO_H
65 #ifndef	IO_H_INCLUDED
66 #include <io.h>
67 #define	IO_H_INCLUDED 1
68 #endif
69 #endif
70 
71 #if	DK4_HAVE_SYSLOG_H
72 #ifndef	SYSLOG_H_INCLUDED
73 #include <syslog.h>
74 #define	SYSLOG_H_INCLUDED 1
75 #endif
76 #endif
77 
78 #if	DK4_HAVE_SYSEXITS_H
79 #ifndef	SYSEXITS_H_INCLUDED
80 #include <sysexits.h>
81 #define	SYSEXITS_H_INCLUDED
82 #endif
83 #endif
84 
85 #ifndef	DK4TYPES_H_INCLUDED
86 #include <libdk4base/dk4types.h>
87 #endif
88 
89 #ifndef	DK4DMT_H_INCLUDED
90 #include <libdk4c/dk4dmt.h>
91 #endif
92 
93 #ifndef	DK4MEM_H_INCLUDED
94 #include <libdk4base/dk4mem.h>
95 #endif
96 
97 #ifndef	DK4MAO8D_H_INCLUDED
98 #include <libdk4maio8d/dk4mao8d.h>
99 #endif
100 
101 #ifndef	DK4STAT8_H_INCLUDED
102 #include <libdk4c/dk4stat8.h>
103 #endif
104 
105 #ifndef	DK4STR8_H_INCLUDED
106 #include <libdk4base/dk4str8.h>
107 #endif
108 
109 #ifndef	DK4FOPC8_H_INCLUDED
110 #include <libdk4c/dk4fopc8.h>
111 #endif
112 
113 #ifndef	DK4MKDH8_H_INCLUDED
114 #include <libdk4c/dk4mkdh8.h>
115 #endif
116 
117 
118 
119 
120 
121 /**	Constant texts used by module.
122 */
123 static char const * const	dk4dmt_kw[] = {
124 /* 0 */
125 "\n",
126 
127 /* 1 */
128 "w",
129 
130 /* 2 */
131 "/dev/null",
132 
133 /* 3 */
134 "/",
135 
136 /* 4 */
137 "No signal handling functions available!",
138 
139 /* 5 */
140 "Failed to create empty set for signal ",
141 
142 /* 6 */
143 "!",
144 
145 /* 7 */
146 "Failed to reset handler for signal ",
147 
148 /* 8 */
149 "!",
150 
151 /* 9 */
152 "Failed to unblock all signals!",
153 
154 /* 10 */
155 "PID file already exists!",
156 
157 /* 11 */
158 "Pipe not open (bug)!",
159 
160 /* 12 */
161 "Failed to read from pipe!",
162 
163 /* 13 */
164 "Failed to fork new process!",
165 
166 /* 14 */
167 "Failed to decouple from terminal using setsid()!",
168 
169 /* 15 */
170 "Missing function to decouple from terminal (setsid/setpgrp)!",
171 
172 /* 16 */
173 "Failed to write PID file!",
174 
175 /* 17 */
176 "No PID file name specified (bug)!",
177 
178 /* 18 */
179 "Failed to duplicate standard file handle using dup2()!",
180 
181 /* 19 */
182 "Failed to open /dev/null for read access!",
183 
184 /* 20 */
185 "Failed to open /dev/null for write access!",
186 
187 /* 21 */
188 "Failed to change to / directory!",
189 
190 /* 22 */
191 "Failed to remove PID file \"",
192 
193 /* 23 */
194 "\"!",
195 
196 /* 24 */
197 "dk4dmt.o",
198 
199 NULL
200 
201 };
202 
203 
204 
205 static
206 void
dk4dmt_log_1(dk4dmt_t * pdmt,size_t i)207 dk4dmt_log_1(dk4dmt_t *pdmt, size_t i)
208 {
209 #if	DK4_HAVE_SYSLOG
210 	const char *progname;
211 #endif
212 	if (0 != pdmt->logstderr) {
213 		fputs(dk4dmt_kw[i], stderr);
214 		fputc('\n', stderr);
215 	}
216 #if	DK4_HAVE_SYSLOG
217 	progname = pdmt->prgname;
218 	if (NULL == progname) { progname = dk4dmt_kw[24]; }
219 	openlog(progname, LOG_PID, pdmt->slf);
220 	syslog(LOG_ERR, "%s", dk4dmt_kw[i]);
221 	closelog();
222 #endif
223 }
224 
225 
226 
227 static
228 void
dk4dmt_log_3(dk4dmt_t * pdmt,size_t i1,size_t i2,const char * s)229 dk4dmt_log_3(dk4dmt_t *pdmt, size_t i1, size_t i2, const char *s)
230 {
231 #if	DK4_HAVE_SYSLOG
232 	const char *progname;
233 #endif
234 	if (0 != pdmt->logstderr) {
235 		fputs(dk4dmt_kw[i1], stderr);
236 		fputs(s, stderr);
237 		fputs(dk4dmt_kw[i2], stderr);
238 		fputc('\n', stderr);
239 	}
240 #if	DK4_HAVE_SYSLOG
241 	progname = pdmt->prgname;
242 	if (NULL == progname) { progname = dk4dmt_kw[24]; }
243 	openlog(progname, LOG_PID, pdmt->slf);
244 	syslog(LOG_ERR, "%s%s%s", dk4dmt_kw[i1], s, dk4dmt_kw[i2]);
245 	closelog();
246 #endif
247 }
248 
249 
250 
251 /**	Set exit status in structure.
252 	@param	pdmt	Structure to modify.
253 	@param	syse	One of the codes defined in the sysexits header.
254 	@param	sdes	Systemd error code.
255 */
256 static
257 void
dk4dmt_set_error_exit_status(dk4dmt_t * pdmt,int syse,int sdes)258 dk4dmt_set_error_exit_status(dk4dmt_t *pdmt, int syse, int sdes)
259 {
260 	if (NULL != pdmt) {
261 		if (EXIT_SUCCESS == pdmt->exv) {
262 #if	DK4_HAVE_SYSTEMD
263 			if (0 != sdes) {
264 				pdmt->exv = sdes;
265 			}
266 			else {
267 				pdmt->exv = syse;
268 			}
269 #else
270 			if (0 != syse) {
271 				pdmt->exv = syse;
272 			}
273 			else {
274 				switch (sdes) {
275 					default : {
276 #if	(DK4_HAVE_SYSEXITS_H) && defined(EX_OSERR)
277 						pdmt->exv = EX_OSERR;
278 #else
279 						pdmt->exv = EXIT_FAILURE;
280 #endif
281 					} break;
282 				}
283 			}
284 #endif
285 		}
286 	}
287 }
288 
289 
290 
291 void
dk4dmt_init(dk4dmt_t * pdmt)292 dk4dmt_init(dk4dmt_t *pdmt)
293 {
294 	if (NULL != pdmt) {
295 		DK4_MEMRES(pdmt,sizeof(dk4dmt_t));
296 		pdmt->prgname = NULL;
297 		pdmt->pidfile	= NULL;
298 		pdmt->pfd[0]	= -1;
299 		pdmt->pfd[1]	= -1;
300 		pdmt->logstderr	=  0;
301 #if	(DK4_HAVE_SYSLOG_H) && defined(LOG_DAEMON)
302 		pdmt->slf		= LOG_DAEMON;
303 #else
304 		pdmt->slf		= (3<<3);
305 #endif
306 		pdmt->exv		= EXIT_SUCCESS;
307 	}
308 }
309 
310 
311 
312 void
dk4dmt_set_program(dk4dmt_t * pdmt,const char * progname)313 dk4dmt_set_program(dk4dmt_t *pdmt, const char *progname)
314 {
315 	if ((NULL != pdmt) && (NULL != progname)) {
316 		pdmt->prgname = progname;
317 	}
318 }
319 
320 
321 
322 void
dk4dmt_set_pidfile(dk4dmt_t * pdmt,const char * pidfile)323 dk4dmt_set_pidfile(dk4dmt_t *pdmt, const char *pidfile)
324 {
325 	if ((NULL != pdmt) && (NULL != pidfile)) {
326 		pdmt->pidfile = pidfile;
327 	}
328 }
329 
330 
331 
332 void
dk4dmt_set_log_stderr(dk4dmt_t * pdmt,int flag)333 dk4dmt_set_log_stderr(dk4dmt_t *pdmt, int flag)
334 {
335 	if (NULL != pdmt) {
336 		pdmt->logstderr = flag;
337 	}
338 }
339 
340 
341 
342 void
dk4dmt_set_syslog_feature(dk4dmt_t * pdmt,int feat)343 dk4dmt_set_syslog_feature(dk4dmt_t *pdmt, int feat)
344 {
345 	if (NULL != pdmt) {
346 		pdmt->slf = feat;
347 	}
348 }
349 
350 
351 
352 void
dk4dmt_error_sigprocmask(dk4dmt_t * pdmt)353 dk4dmt_error_sigprocmask(dk4dmt_t *pdmt)
354 {
355 #if	(DK4_HAVE_SYSEXITS_H) && defined(EX_OSERR)
356 	dk4dmt_set_error_exit_status(pdmt, EX_OSERR, 207);
357 #else
358 	dk4dmt_set_error_exit_status(pdmt, EXIT_FAILURE, 207);
359 #endif
360 }
361 
362 
363 
364 void
dk4dmt_error_sigemptyset(dk4dmt_t * pdmt)365 dk4dmt_error_sigemptyset(dk4dmt_t *pdmt)
366 {
367 #if	(DK4_HAVE_SYSEXITS_H) && defined(EX_OSERR)
368 	dk4dmt_set_error_exit_status(pdmt, EX_OSERR, 207);
369 #else
370 	dk4dmt_set_error_exit_status(pdmt, EXIT_FAILURE, 207);
371 #endif
372 }
373 
374 
375 
376 void
dk4dmt_error_no_signal_function(dk4dmt_t * pdmt)377 dk4dmt_error_no_signal_function(dk4dmt_t *pdmt)
378 {
379 #if	(DK4_HAVE_SYSEXITS_H) && defined(EX_OSERR)
380 	dk4dmt_set_error_exit_status(pdmt, EX_OSERR, 2);
381 #else
382 	dk4dmt_set_error_exit_status(pdmt, EXIT_FAILURE, 2);
383 #endif
384 }
385 
386 
387 
388 void
dk4dmt_error_pid_file_exists(dk4dmt_t * pdmt)389 dk4dmt_error_pid_file_exists(dk4dmt_t *pdmt)
390 {
391 #if	(DK4_HAVE_SYSEXITS_H) && defined(EX_SOFTWARE)
392 	dk4dmt_set_error_exit_status(pdmt, EX_SOFTWARE, 0);
393 #else
394 	dk4dmt_set_error_exit_status(pdmt, EXIT_FAILURE, 0);
395 #endif
396 }
397 
398 
399 
400 void
dk4dmt_error_pid_file_name_missing(dk4dmt_t * pdmt)401 dk4dmt_error_pid_file_name_missing(dk4dmt_t *pdmt)
402 {
403 #if	(DK4_HAVE_SYSEXITS_H) && defined(EX_SOFTWARE)
404 	dk4dmt_set_error_exit_status(pdmt, EX_SOFTWARE, 0);
405 #else
406 	dk4dmt_set_error_exit_status(pdmt, EXIT_FAILURE, 0);
407 #endif
408 }
409 
410 
411 
412 void
dk4dmt_error_pipe_not_open(dk4dmt_t * pdmt)413 dk4dmt_error_pipe_not_open(dk4dmt_t *pdmt)
414 {
415 #if	(DK4_HAVE_SYSEXITS_H) && defined(EX_SOFTWARE)
416 	dk4dmt_set_error_exit_status(pdmt, EX_SOFTWARE, 0);
417 #else
418 	dk4dmt_set_error_exit_status(pdmt, EXIT_FAILURE, 0);
419 #endif
420 }
421 
422 
423 
424 void
dk4dmt_error_pipe_read_failed(dk4dmt_t * pdmt)425 dk4dmt_error_pipe_read_failed(dk4dmt_t *pdmt)
426 {
427 #if	(DK4_HAVE_SYSEXITS_H) && defined(EX_IOERR)
428 	dk4dmt_set_error_exit_status(pdmt, EX_IOERR, 0);
429 #else
430 	dk4dmt_set_error_exit_status(pdmt, EXIT_FAILURE, 0);
431 #endif
432 }
433 
434 
435 
436 void
dk4dmt_error_fork_failed(dk4dmt_t * pdmt)437 dk4dmt_error_fork_failed(dk4dmt_t *pdmt)
438 {
439 #if	(DK4_HAVE_SYSEXITS_H) && defined(EX_OSERR)
440 	dk4dmt_set_error_exit_status(pdmt, EX_OSERR, 0);
441 #else
442 	dk4dmt_set_error_exit_status(pdmt, EXIT_FAILURE, 0);
443 #endif
444 }
445 
446 
447 
448 void
dk4dmt_error_dup2_failed(dk4dmt_t * pdmt)449 dk4dmt_error_dup2_failed(dk4dmt_t *pdmt)
450 {
451 #if	(DK4_HAVE_SYSEXITS_H) && defined(EX_IOERR)
452 	dk4dmt_set_error_exit_status(pdmt, EX_IOERR, 0);
453 #else
454 	dk4dmt_set_error_exit_status(pdmt, EXIT_FAILURE, 0);
455 #endif
456 }
457 
458 
459 
460 void
dk4dmt_error_failed_read_dev_null(dk4dmt_t * pdmt)461 dk4dmt_error_failed_read_dev_null(dk4dmt_t *pdmt)
462 {
463 #if	(DK4_HAVE_SYSEXITS_H) && defined(EX_IOERR)
464 	dk4dmt_set_error_exit_status(pdmt, EX_IOERR, 0);
465 #else
466 	dk4dmt_set_error_exit_status(pdmt, EXIT_FAILURE, 0);
467 #endif
468 }
469 
470 
471 
472 void
dk4dmt_error_failed_write_dev_null(dk4dmt_t * pdmt)473 dk4dmt_error_failed_write_dev_null(dk4dmt_t *pdmt)
474 {
475 #if	(DK4_HAVE_SYSEXITS_H) && defined(EX_IOERR)
476 	dk4dmt_set_error_exit_status(pdmt, EX_IOERR, 0);
477 #else
478 	dk4dmt_set_error_exit_status(pdmt, EXIT_FAILURE, 0);
479 #endif
480 }
481 
482 
483 
484 void
dk4dmt_error_failed_chdir_root(dk4dmt_t * pdmt)485 dk4dmt_error_failed_chdir_root(dk4dmt_t *pdmt)
486 {
487 #if	(DK4_HAVE_SYSEXITS_H) && defined(EX_OSERR)
488 	dk4dmt_set_error_exit_status(pdmt, EX_OSERR, 200);
489 #else
490 	dk4dmt_set_error_exit_status(pdmt, EXIT_FAILURE, 200);
491 #endif
492 }
493 
494 
495 
496 void
dk4dmt_error_setsid(dk4dmt_t * pdmt)497 dk4dmt_error_setsid(dk4dmt_t *pdmt)
498 {
499 #if	(DK4_HAVE_SYSEXITS_H) && defined(EX_OSERR)
500 	dk4dmt_set_error_exit_status(pdmt, EX_OSERR, 220);
501 #else
502 	dk4dmt_set_error_exit_status(pdmt, EXIT_FAILURE, 220);
503 #endif
504 }
505 
506 
507 void
dk4dmt_error_write_pid_file(dk4dmt_t * pdmt)508 dk4dmt_error_write_pid_file(dk4dmt_t *pdmt)
509 {
510 #if	(DK4_HAVE_SYSEXITS_H) && defined(EX_IOERR)
511 	dk4dmt_set_error_exit_status(pdmt, EX_IOERR, 0);
512 #else
513 	dk4dmt_set_error_exit_status(pdmt, EXIT_FAILURE, 0);
514 #endif
515 }
516 
517 
518 
519 void
dk4dmt_error_sysfct(dk4dmt_t * pdmt)520 dk4dmt_error_sysfct(dk4dmt_t *pdmt)
521 {
522 	if (NULL != pdmt) {
523 #if	(DK4_HAVE_SYSEXITS_H) && defined(EX_OSERR)
524 		dk4dmt_set_error_exit_status(pdmt, EX_OSERR, 0);
525 #else
526 		dk4dmt_set_error_exit_status(pdmt, EXIT_FAILURE, 0);
527 #endif
528 	}
529 }
530 
531 
532 
533 void
dk4dmt_error_usage(dk4dmt_t * pdmt)534 dk4dmt_error_usage(dk4dmt_t *pdmt)
535 {
536 	if (NULL != pdmt) {
537 #if	(DK4_HAVE_SYSEXITS_H) && defined(EX_USAGE)
538 		dk4dmt_set_error_exit_status(pdmt, EX_USAGE, 0);
539 #else
540 		dk4dmt_set_error_exit_status(pdmt, EXIT_FAILURE, 0);
541 #endif
542 	}
543 }
544 
545 
546 
547 void
dk4dmt_error_config(dk4dmt_t * pdmt)548 dk4dmt_error_config(dk4dmt_t *pdmt)
549 {
550 	if (NULL != pdmt) {
551 #if	(DK4_HAVE_SYSEXITS_H) && defined(EX_CONFIG)
552 		dk4dmt_set_error_exit_status(pdmt, EX_CONFIG, 0);
553 #else
554 		dk4dmt_set_error_exit_status(pdmt, EXIT_FAILURE, 0);
555 #endif
556 	}
557 }
558 
559 
560 
561 static
562 void
dk4dmt_reset_all_signals(int * pback,dk4dmt_t * pdmt)563 dk4dmt_reset_all_signals(int *pback, dk4dmt_t *pdmt)
564 {
565 #if	DK4_HAVE_SIGACTION
566 	struct sigaction	sigact;		/* Information for sigaction() */
567 #endif
568 	char				buf[16*sizeof(int)];
569 	int					maxsig;		/* Maximum signal number */
570 	int					signo;		/* Current signal number to process */
571 	int					go;			/* Flag: Reconfigure signal */
572 	int					ec;			/* Error code */
573 
574 	ec = 0;
575 #ifdef	_NSIG
576 	maxsig = _NSIG;
577 #else
578 	maxsig = 16;
579 #endif
580 	for (signo = 1; ((maxsig >= signo) && (1 == *pback)); signo++) {
581 		go = 1;
582 #ifdef	SIGKILL
583 		if (SIGKILL == signo) { go = 0; }
584 #else
585 		if (9 == signo) { go = 0; }
586 #endif
587 #ifdef	SIGSTOP
588 		if (SIGSTOP == signo) { go = 0; }
589 #else
590 		if (19 == signo) { go = 0; }
591 #endif
592 		if (0 != go) {
593 #if	DK4_HAVE_SIGACTION
594 			DK4_MEMRES(&sigact, sizeof(sigact));
595 			sigact.sa_handler = SIG_DFL;
596 			sigact.sa_flags   = 0;
597 			if (0 != sigemptyset(&(sigact.sa_mask))) {
598 				if (16 > signo) {
599 					*pback = 0;
600 					dk4dmt_error_sigemptyset(pdmt);
601 					/* ERROR: Failed to empty set */
602 #if	DK4_HAVE_SNPRINTF
603 					snprintf(buf, sizeof(buf), "%d", signo);
604 #else
605 					sprintf(buf, "%d", signo);
606 #endif
607 					dk4dmt_log_3(pdmt, 5, 6, buf);
608 				}
609 			}
610 			else {
611 				if (0 != sigaction(signo, &sigact, NULL)) {
612 					if (16 > signo) {
613 						*pback = 0;
614 						dk4dmt_error_sigemptyset(pdmt);
615 						/* ERROR: sigaction failed */
616 #if	DK4_HAVE_SNPRINTF
617 						snprintf(buf, sizeof(buf), "%d", signo);
618 #else
619 						sprintf(buf, "%d", signo);
620 #endif
621 						dk4dmt_log_3(pdmt, 7, 8, buf);
622 					}
623 				}
624 			}
625 #else
626 #if	DK4_HAVE_SIGSET
627 			sigset(signo, SIG_DFL);
628 #else
629 #if	DK4_HAVE_SIGNAL
630 			signal(signo, SIG_DFL);
631 #else
632 			*pback = 0;
633 			dk4dmt_error_no_signal_function(pdmt);
634 			/* ERROR: No function available to modify signals */
635 			if (0 == ec) { ec = 3; }
636 #endif
637 #endif
638 #endif
639 		}
640 	}
641 	switch (ec) {
642 		case 3: {
643 			dk4dmt_log_1(pdmt, 4);
644 		} break;
645 	}
646 }
647 
648 
649 
650 static
651 void
dk4dmt_unblock_all_signals(int * pback,dk4dmt_t * pdmt)652 dk4dmt_unblock_all_signals(int *pback, dk4dmt_t *pdmt)
653 {
654 	sigset_t	set;
655 	if (0 == sigemptyset(&set)) {
656 		if (0 != sigprocmask(SIG_SETMASK, &set, NULL)) {
657 			*pback = 0;
658 			dk4dmt_error_sigprocmask(pdmt);
659 			/* ERROR: sigprocmask failed */
660 			dk4dmt_log_1(pdmt, 9);
661 		}
662 	}
663 	else {
664 		*pback = 0;
665 		dk4dmt_error_sigemptyset(pdmt);
666 		/* ERROR: Failed to sigemptyset */
667 		dk4dmt_log_1(pdmt, 9);
668 	}
669 }
670 
671 
672 
673 static
674 void
dk4dmt_close_non_std_file_descriptors(void)675 dk4dmt_close_non_std_file_descriptors(void)
676 {
677 #if	DK4_HAVE_SYS_RESOURCE_H && DK4_HAVE_GETRLIMIT && defined(RLIMIT_NOFILE)
678 	struct rlimit	rl;
679 #endif
680 	int				maxfd	=	1024;
681 	int				fd;
682 
683 	/*	Find maximum file descriptor
684 	*/
685 #if	DK4_HAVE_SYS_RESOURCE_H && DK4_HAVE_GETRLIMIT && defined(RLIMIT_NOFILE)
686 	if (0 == getrlimit(RLIMIT_NOFILE, &rl)) {
687 #if	defined(RLIM_INFINITY)
688 		if (RLIM_INFINITY != rl.rlim_max) {
689 			back = rl.rlim_max;
690 		}
691 #else
692 		back = rl.rlim_max;
693 #endif
694 	}
695 #else
696 #endif
697 	/*
698 		Close file descriptors
699 	*/
700 	for (fd = 3; fd <= maxfd; fd++) {
701 		(void)close(fd);
702 	}
703 }
704 
705 
706 
707 int
dk4dmt_parent_before_fork(dk4dmt_t * pdmt)708 dk4dmt_parent_before_fork(dk4dmt_t *pdmt)
709 {
710 	dk4_stat_t	 stb;
711 	int			 back	= 0;
712 
713 	if (NULL != pdmt) {
714 		back = 1;
715 		/*
716 			Close non-standard file descriptors
717 		*/
718 		dk4dmt_close_non_std_file_descriptors();
719 		/*
720 			Reset all signals
721 		*/
722 		dk4dmt_reset_all_signals(&back, pdmt);
723 		if (1 == back) {
724 			/*
725 				Unblock all signals
726 			*/
727 			dk4dmt_unblock_all_signals(&back, pdmt);
728 			if (1 == back) {
729 				if (NULL != pdmt->pidfile) {
730 					if (0 != dk4stat_c8(&stb, pdmt->pidfile, NULL)) {
731 						back = 0;
732 						dk4dmt_error_pid_file_exists(pdmt);
733 						/* ERROR: PID file exists */
734 						dk4dmt_log_1(pdmt, 10);
735 					}
736 				}
737 				if (1 == back) {
738 					if (0 != pipe(&(pdmt->pfd[0]))) {
739 						back = 0;
740 						pdmt->pfd[0] = -1;
741 						pdmt->pfd[1] = -1;
742 					}
743 				}
744 			}
745 		}
746 	}
747 	return back;
748 }
749 
750 
751 
752 void
dk4dmt_parent_after_fork(dk4dmt_t * pdmt)753 dk4dmt_parent_after_fork(dk4dmt_t *pdmt)
754 {
755 	int		v;
756 
757 	if (NULL != pdmt) {
758 		/*
759 			Close write head
760 		*/
761 		if (-1 != pdmt->pfd[1]) {
762 			close(pdmt->pfd[1]);
763 			pdmt->pfd[1] = -1;
764 		}
765 		else {
766 			dk4dmt_error_pipe_not_open(pdmt);
767 			/* ERROR: Pipe was not open (bug) */
768 			dk4dmt_log_1(pdmt, 11);
769 		}
770 		/*
771 			Read exit status code and close read head
772 		*/
773 		if (-1 != pdmt->pfd[0]) {
774 			if ((int)sizeof(int) == (int)read(pdmt->pfd[0], &v, sizeof(int))) {
775 				pdmt->exv = v;
776 			}
777 			else {
778 				dk4dmt_error_pipe_read_failed(pdmt);
779 				/* ERROR: Failed to read from pipe */
780 				dk4dmt_log_1(pdmt, 12);
781 			}
782 			close(pdmt->pfd[0]);
783 			pdmt->pfd[0] = -1;
784 		}
785 		else {
786 			dk4dmt_error_pipe_not_open(pdmt);
787 			/* ERROR: Pipe was not open (bug) */
788 			dk4dmt_log_1(pdmt, 11);
789 		}
790 	}
791 }
792 
793 
794 
795 void
dk4dmt_parent_fork_failed(dk4dmt_t * pdmt)796 dk4dmt_parent_fork_failed(dk4dmt_t *pdmt)
797 {
798 	if (NULL != pdmt) {
799 		/*
800 			Write error exit status code
801 		*/
802 		dk4dmt_error_fork_failed(pdmt);
803 		/* ERROR: Fork failed */
804 		dk4dmt_log_1(pdmt, 13);
805 		/*
806 			Close write head
807 		*/
808 		if (-1 != pdmt->pfd[1]) {
809 			close(pdmt->pfd[1]);
810 			pdmt->pfd[1] = -1;
811 		}
812 		/*
813 			Close read head
814 		*/
815 		if (-1 != pdmt->pfd[0]) {
816 			close(pdmt->pfd[0]);
817 			pdmt->pfd[0] = -1;
818 		}
819 	}
820 }
821 
822 
823 
824 int
dk4dmt_intermediate_before_fork(dk4dmt_t * pdmt)825 dk4dmt_intermediate_before_fork(dk4dmt_t *pdmt)
826 {
827 	int		 back	= 0;
828 	if (NULL != pdmt) {
829 		back = 1;
830 		/*
831 			Close read head
832 		*/
833 		if (-1 != pdmt->pfd[0]) {
834 			close(pdmt->pfd[0]);
835 			pdmt->pfd[0] = -1;
836 		}
837 #if	DK4_HAVE_SETSID
838 		if ((pid_t)(-1) == setsid()) {
839 			back = 0;
840 			dk4dmt_error_setsid(pdmt);
841 			/* ERROR: setsid() failed */
842 			dk4dmt_log_1(pdmt, 14);
843 		}
844 #else
845 #if	DK4_HAVE_SETPGRP
846 		setpgrp();
847 #else
848 		back = 0;
849 		dk4dmt_error_setsid(pdmt);
850 		/* ERROR: No function to decouple from terminal */
851 		dk4dmt_log_1(pdmt, 15);
852 #endif
853 #endif
854 	}
855 	return back;
856 }
857 
858 
859 
860 void
dk4dmt_intermediate_after_fork(dk4dmt_t * pdmt)861 dk4dmt_intermediate_after_fork(dk4dmt_t *pdmt)
862 {
863 	if (NULL != pdmt) {
864 		/*
865 			Close write head
866 		*/
867 		if (-1 != pdmt->pfd[1]) {
868 			close(pdmt->pfd[1]);
869 			pdmt->pfd[1] = -1;
870 		}
871 	}
872 }
873 
874 
875 
876 void
dk4dmt_intermediate_fork_failed(dk4dmt_t * pdmt)877 dk4dmt_intermediate_fork_failed(dk4dmt_t *pdmt)
878 {
879 	int v;
880 
881 	if (NULL != pdmt) {
882 		/*
883 			Set exit status code
884 		*/
885 		dk4dmt_parent_fork_failed(pdmt);
886 		/* ERROR: Fork failed */
887 		dk4dmt_log_1(pdmt, 13);
888 		/*
889 			Close write head
890 		*/
891 		if (-1 != pdmt->pfd[1]) {
892 			v = pdmt->exv;
893 			if ((int)sizeof(v) != (int)write(pdmt->pfd[1], &v, sizeof(v))) {
894 #if	(DK4_HAVE_SYSEXITS_H) && defined(EX_IOERR)
895 				dk4dmt_set_error_exit_status(pdmt, EX_IOERR, 0);
896 #else
897 				dk4dmt_set_error_exit_status(pdmt, EXIT_FAILURE, 0);
898 #endif
899 			}
900 			close(pdmt->pfd[1]);
901 			pdmt->pfd[1] = -1;
902 		}
903 	}
904 }
905 
906 
907 
908 int
dk4dmt_daemon_start(dk4dmt_t * pdmt)909 dk4dmt_daemon_start(dk4dmt_t *pdmt)
910 {
911 	char		 pidbuf[16*sizeof(dk4_um_t)];
912 	FILE		*fipo;
913 	int			 res;
914 	int			 v;
915 	int			 fdout;
916 	int			 fdin;
917 	int			 back	= 0;
918 
919 	if (NULL != pdmt) {
920 		if (NULL != pdmt->pidfile) {
921 			res = dk4ma_write_c8_decimal_unsigned(
922 				pidbuf, sizeof(pidbuf), (dk4_um_t)getpid(), 0, NULL
923 			);
924 			if (0 != res) {
925 				if (0 != dk4str8_cat_s(pidbuf,sizeof(pidbuf),dk4dmt_kw[0],NULL))
926 				{
927 					(void)dk4mkdir_hierarchy_c8(pdmt->pidfile, 0, NULL);
928 					fipo = dk4fopen_c8(
929 						pdmt->pidfile,dk4dmt_kw[1],DK4_FOPEN_SC_PRIVILEGED,NULL
930 					);
931 					if (NULL != fipo) {
932 						back = 1;
933 						if (EOF == fputs(pidbuf, fipo)) {
934 							back = 0;
935 							dk4dmt_error_write_pid_file(pdmt);
936 							/* ERROR: Failed to write PID file */
937 							dk4dmt_log_1(pdmt, 16);
938 						}
939 						if (0 != fclose(fipo)) {
940 							back = 0;
941 							dk4dmt_error_write_pid_file(pdmt);
942 							/* ERROR: Failed to write PID file */
943 							dk4dmt_log_1(pdmt, 16);
944 						}
945 					}
946 					else {
947 						dk4dmt_error_write_pid_file(pdmt);
948 						/* ERROR: Failed to write PID file */
949 						dk4dmt_log_1(pdmt, 16);
950 					}
951 				}
952 			}
953 			if (0 == back) {
954 				unlink(pdmt->pidfile);
955 			}
956 		}
957 		else {
958 			dk4dmt_error_pid_file_name_missing(pdmt);
959 			/* ERROR: Missing PID file name */
960 			dk4dmt_log_1(pdmt, 17);
961 		}
962 		/*
963 			Connect /dev/null to stdin, stdout and stderr
964 		*/
965 		if (0 != back) {
966 			fdin = open(dk4dmt_kw[2], O_RDONLY);
967 			if (-1 < fdin) {
968 				if (-1 == dup2(fdin, 0)) {
969 					back = 0;
970 					dk4dmt_error_dup2_failed(pdmt);
971 					/* ERROR: Failed to duplicate file handle */
972 					dk4dmt_log_1(pdmt, 18);
973 				}
974 				close(fdin);
975 			}
976 			else {
977 				back = 0;
978 				dk4dmt_error_failed_read_dev_null(pdmt);
979 				/* ERROR: Failed to read /dev/null */
980 				dk4dmt_log_1(pdmt, 19);
981 			}
982 			fdout = open(dk4dmt_kw[2], O_WRONLY);
983 			if (-1 < fdout) {
984 				if (-1 == dup2(fdout, 1)) {
985 					back = 0;
986 					dk4dmt_error_dup2_failed(pdmt);
987 					/* ERROR: Failed to duplicate file handle */
988 					dk4dmt_log_1(pdmt, 18);
989 				}
990 				if (-1 == dup2(fdout, 2)) {
991 					back = 0;
992 					dk4dmt_error_dup2_failed(pdmt);
993 					/* ERROR: Failed to duplicate file handle */
994 					dk4dmt_log_1(pdmt, 18);
995 				}
996 				close(fdout);
997 			}
998 			else {
999 				back = 0;
1000 				dk4dmt_error_failed_write_dev_null(pdmt);
1001 				/* ERROR: Failed to write /dev/null */
1002 				dk4dmt_log_1(pdmt, 20);
1003 			}
1004 		}
1005 		/*
1006 			Use exact permissions when creating new files or directories
1007 		*/
1008 		if (0 != back) {
1009 			umask(0);
1010 		}
1011 		/*
1012 			Change to root directory
1013 		*/
1014 		if (0 != back) {
1015 			if (0 != chdir(dk4dmt_kw[3])) {
1016 				back = 0;
1017 				dk4dmt_error_failed_chdir_root(pdmt);
1018 				/* ERROR: Failed to change into root directory */
1019 				dk4dmt_log_1(pdmt, 21);
1020 			}
1021 		}
1022 		/*	Send exit status code to main process
1023 		*/
1024 		if (-1 != pdmt->pfd[1]) {
1025 			v = pdmt->exv;
1026 			if ((int)sizeof(v) != (int)write(pdmt->pfd[1], &v, sizeof(v))) {
1027 #if	(DK4_HAVE_SYSEXITS_H) && defined(EX_IOERR)
1028 				dk4dmt_set_error_exit_status(pdmt, EX_IOERR, 0);
1029 #else
1030 				dk4dmt_set_error_exit_status(pdmt, EXIT_FAILURE, 0);
1031 #endif
1032 			}
1033 			close(pdmt->pfd[1]);
1034 			pdmt->pfd[1] = -1;
1035 		}
1036 	}
1037 	return back;
1038 }
1039 
1040 
1041 
1042 void
dk4dmt_daemon_end(dk4dmt_t * pdmt)1043 dk4dmt_daemon_end(dk4dmt_t *pdmt)
1044 {
1045 	if (NULL != pdmt) {
1046 		if (NULL != pdmt->pidfile) {
1047 			if (0 != unlink(pdmt->pidfile)) {
1048 				/* ERROR: Failed to remove PID file */
1049 				dk4dmt_log_3(pdmt, 22, 23, pdmt->pidfile);
1050 			}
1051 		}
1052 	}
1053 }
1054 
1055 
1056 
1057 void
dk4dmt_success(dk4dmt_t * pdmt)1058 dk4dmt_success(dk4dmt_t *pdmt)
1059 {
1060 	if (NULL != pdmt) {
1061 		pdmt->exv = EXIT_SUCCESS;
1062 	}
1063 }
1064 
1065 
1066 int
dk4dmt_get_exit_status(dk4dmt_t * pdmt)1067 dk4dmt_get_exit_status(dk4dmt_t *pdmt)
1068 {
1069 	int	back	= EXIT_FAILURE;
1070 	if (NULL != pdmt) {
1071 		back = pdmt->exv;
1072 	}
1073 	return back;
1074 }
1075 
1076 
1077 /* vim: set ai sw=4 ts=4 : */
1078 
1079