diff options
author | Norbert Preining <norbert@preining.info> | 2020-09-20 03:03:26 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2020-09-20 03:03:26 +0000 |
commit | 1f457376b478257b88d4a857f5ec1b6155442dd7 (patch) | |
tree | 2a06a60551dea362cf8cb0cb0ba66c78608717c4 /support/dktools/dk4dmt.h | |
parent | ac690ca29ad5bf8a5203a65fd6252f7b564f4727 (diff) |
CTAN sync 202009200303
Diffstat (limited to 'support/dktools/dk4dmt.h')
-rw-r--r-- | support/dktools/dk4dmt.h | 450 |
1 files changed, 362 insertions, 88 deletions
diff --git a/support/dktools/dk4dmt.h b/support/dktools/dk4dmt.h index b2a1059b5c..24d17a897c 100644 --- a/support/dktools/dk4dmt.h +++ b/support/dktools/dk4dmt.h @@ -1,36 +1,14 @@ /* - WARNING: This file was generated by dkct. - Changes you make here will be lost if dkct is run again! - You should modify the original source and run dkct on it. - Original source: dk4dmt.ctr +Copyright (C) 2019-2020, Dirk Krause +SPDX-License-Identifier: BSD-3-Clause */ /* -Copyright (C) 2016-2017, Dirk Krause - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above opyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. -* Neither the name of the author nor the names of contributors may be used - to endorse or promote products derived from this software without specific - prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + WARNING: This file was generated by the dkct program (see + http://dktools.sourceforge.net/ for details). + Changes you make here will be lost if dkct is run again! + You should modify the original source and run dkct on it. + Original source: dk4dmt.ctr */ #ifndef DK4DMT_H_INCLUDED @@ -38,16 +16,20 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define DK4DMT_H_INCLUDED 1 -#line 8 "dk4dmt.ctr" +#line 9 "dk4dmt.ctr" -/** @file dk4dmt.h Daemon tools. +/** @file dk4dmt.h Daemon tool functions. -The functions in this module can be used in standing daemons. +The functions in this module can be used to program standing daemons. +Three processes are involved in a standing daemon: + +* master process, originally started, +* intermediate process, forked by master, decouples from terminal and +* daemon process, forked by intermediate process. + +When a standing daemon is started by a systemd service unit, the master +process must not exit before the daemon process has created the PID file. -In the original process, call the -dk4dmt_parent_before_fork() function to close all file descriptors -above 2, reset all signal handlers to defaults, unblock all signals -and check whether a PID file already exists. If you plan to give up root privileges in the child processes (use setgid() and setuid() to change effective user and group), do not use /var/run/<i>program</i>.pid as PID file name, better @@ -57,77 +39,369 @@ to the unprivileged user and group used by the child process. User and group need write permission to the directory, so the unprivileged child process can remove the PID file when exiting. -In the intermediate process after the first fork call -dk4dmt_intermediate_before_fork(). Among other things this function -completely decouples the process from the terminal. +The general usage structure looks like this: + +@code +#define PROGRAM_NAME "my-new-service" +const char program_name[] = { + PROGRAM_NAME +}; +const char pid_file_name[] = { + "/run/" PROGRAM_NAME "/" PROGRAM_NAME ".pid" +}; +dk4dmt_t dmt; -In the final process (after forking again) call -dk4dmt_daemon_after_fork() -to set up things before starting service. This function creates the PID -file, connects file descriptors 0, 1 and 2 to /dev/null, resets -the umask and changes into the / directory. +... -After finishing service call -dk4dmt_daemon_end() before exiting. This function removes the PID -file. +pid_t cpid; +dk4dmt_init(&dmt); +if (0 != read_configuration_file()) { + dk4dmt_set_program(&dmt, program_name); + dk4dmt_set_pidfile(&dmt, pid_file_name); + dk4dmt_set_syslog_feature(&dmt, syslog_feature); + if (0 != dk4dmt_parent_before_fork(&dmt)) { + cpid = fork(); + if ((pid_t)0 == cpid) { + if (0 != dk4dmt_intermediate_before_fork(&dmt)) { + cpid = fork(); + if ((pid_t)0 == cpid) { + if (0 != dk4dmt_daemon_start(&dmt)) { + do_the_service(); + } + dk4dmt_daemon_end(&dmt); + } + else { + if ((pid_t)(-1) != cpid) { + dk4dmt_intermediate_after_fork(&dmt); + } + else { + dk4dmt_intermediate_fork_failed(&dmt); + } + } + } + } + else { + if ((pid_t)(-1) != cpid) { + dk4dmt_parent_after_fork(&dmt); + } + else { + dk4dmt_parent_fork_failed(&dmt); + } + } + } +} +else { + dk4dmt_error_config(&dmt); +} +exval = dk4dmt_get_exit_status(&dmt); +exit(exval); +@endcode + +*/ + +#ifndef DK4CONF_H_INCLUDED +#if DK4_BUILDING_DKTOOLS4 +#include "dk4conf.h" +#else +#include <dktools-4/dk4conf.h> +#endif +#endif + + +/** Data collection for daemon. */ +typedef struct { + char const *prgname; /**< Program name. */ + char const *pidfile; /**< PID file name. */ + int pfd[2]; /**< Pipe file descriptors. */ + int logstderr; /**< Flag: Logging to stderr allowed. */ + int slf; /**< Syslog feature. */ + int exv; /**< Exit status code to return. */ +} dk4dmt_t; + -#ifdef __cplusplus + +#ifdef __cplusplus extern "C" { #endif -/** Activities in parent process before calling fork(). - * Close all file descriptors above 2. - * Reset all signal actions to default handlers. - * Unblock all signals. - * Check whether PID file already exists. - Use this function to check whether the initial process - can run fork(). - @param prgname Program name. - @param pidfilename PID file name. - @param logstderr Flag: Logging to stderr allowed. - @param slf Syslog feature. - @return 1 on success (can call fork), 0 on error (abort). +/** Initialize daemon tool structure. + @param pdmt Daemon tool structure to initialize. */ -int -dk4dmt_parent_before_fork( - const char *prgname, const char *pidfilename, int logstderr, int slf -); + +void +dk4dmt_init(dk4dmt_t *pdmt); + + +/** Set program name for daemon tool structure. + The function does not create a copy of the program name, + it keeps the original pointer in the structure. + So the progname buffer must exist and contain data as long as + the structure is used. + @param pdmt Daemon tool structure to set up. + @param progname Program name. +*/ + +void +dk4dmt_set_program(dk4dmt_t *pdmt, const char *progname); + + +/** Set PID file name for daemon tool structure. + The function does not create a copy of the file name, it keeps the original + pointer in the structure. + So the pidfile buffer must exist and contain data as long as + the structure is used. + @param pdmt Daemon tool structure to set up. + @param pidfile PID file name. +*/ + +void +dk4dmt_set_pidfile(dk4dmt_t *pdmt, const char *pidfile); + + +/** Enable or disable logging to stderr for daemon tool structure. + @param pdmt Daemon tool structure to set up. + @param flag Allow or deny logging to stderr. +*/ + +void +dk4dmt_set_log_stderr(dk4dmt_t *pdmt, int flag); + + +/** Set syslog feature for daemon tool structure. + @param pdmt Daemon tool structure to set up. + @param feat Syslog feature to use. +*/ + +void +dk4dmt_set_syslog_feature(dk4dmt_t *pdmt, int feat); -/** Activities in first child before calling fork() again. - * Decouple completely from terminal. - Use this function to check whether the first child process - can run fork() again. - @param prgname Program name. - @param slf Syslog feature. - @return 1 on success (can call fork), 0 on error (abort). +/** Process initialization before first fork attempt. + Open pipe for communication from daemon to parent. + @param pdmt Daemon tool structure to use. + @return 1 on success, 0 on error. */ + int -dk4dmt_intermediate_before_fork(const char *prgname, int slf); - -/** Activities in final daemon process. - * Create PID file. - * Connect file descriptors 0, 1 and 2 to /dev/null. - * Reset umask. - * Change into / directory. - @param prgname Program name. - @param pidfilename File name for PID file. - @param slf Syslog feature. +dk4dmt_parent_before_fork(dk4dmt_t *pdmt); + + +/** Wait for startup completion notification in parent process. + Close write head, read exit status, close read head. + @param pdmt Daemon tool structure to use. +*/ + +void +dk4dmt_parent_after_fork(dk4dmt_t *pdmt); + + +/** React on failed fork attempt in parent process. + Close both pipe heads. + @param pdmt Daemon tool structure to use. +*/ + +void +dk4dmt_parent_fork_failed(dk4dmt_t *pdmt); + + +/** Prepare for second fork attempt in intermediate process. + Close read head. + On error write exit status code and close write pipe head. + @param pdmt Daemon tool structure to use. @return 1 on success, 0 on error. */ + +int +dk4dmt_intermediate_before_fork(dk4dmt_t *pdmt); + + +/** Clean up in intermediate process after forking the daemon. + Close write pipe head. + @param pdmt Daemon tool structure to use. +*/ + +void +dk4dmt_intermediate_after_fork(dk4dmt_t *pdmt); + + +/** React on failed fork attempt in intermediate process. + Write exit status code and close write pipe head. + @param pdmt Daemon tool structure to use. +*/ + +void +dk4dmt_intermediate_fork_failed(dk4dmt_t *pdmt); + + +/** Create PID file and notify main process to exit. + Write exit status and close write pipe head. + @param pdmt Daemon tool structure to use. +*/ + int -dk4dmt_daemon_after_fork(const char *prgname, const char *pidfilename, int slf); +dk4dmt_daemon_start(dk4dmt_t *pdmt); + + +/** Clean up daemon structure before exiting daemon process (remove PID file). + @param pdmt Daemon tool structure to use. +*/ + +void +dk4dmt_daemon_end(dk4dmt_t *pdmt); + + +/** Set exit code in daemon structure for failed system function. + @param pdmt Daemon tool structure to use. +*/ + +void +dk4dmt_error_sysfct(dk4dmt_t *pdmt); + -/** End of daemon, remove PID file. - @param prgname Program name. - @param pidfilename PID file name. - @param slf Syslog feature. +/** Set exit code in daemon structure for failed signal process mask. + @param pdmt Daemon tool structure to use. */ + +void +dk4dmt_error_sigprocmask(dk4dmt_t *pdmt); + + +/** Set exit code in daemon structure to indicate missing signal functionality. + @param pdmt Daemon tool structure to use. +*/ + +void +dk4dmt_error_no_signal_function(dk4dmt_t *pdmt); + + +/** Set exit code in daemon structure to indicate PID file exists. + @param pdmt Daemon tool structure to use. +*/ + +void +dk4dmt_error_pid_file_exists(dk4dmt_t *pdmt); + + +/** Set exit code in daemon structure to indicate PID file not configured. + @param pdmt Daemon tool structure to use. +*/ + +void +dk4dmt_error_pid_file_name_missing(dk4dmt_t *pdmt); + + +/** Set exit code in daemon structure to indicate write PID file failed. + @param pdmt Daemon tool structure to use. +*/ + +void +dk4dmt_error_write_pid_file(dk4dmt_t *pdmt); + +/** Set exit code in daemon structure to indicate pipe was not opened (bug). + @param pdmt Daemon tool structure to use. +*/ + +void +dk4dmt_error_pipe_not_open(dk4dmt_t *pdmt); + + +/** Set exit code in daemon structure to indicate reading from pipe failed. + @param pdmt Daemon tool structure to use. +*/ + +void +dk4dmt_error_pipe_read_failed(dk4dmt_t *pdmt); + + +/** Set exit code in daemon structure to indicate fork failed. + @param pdmt Daemon tool structure to use. +*/ + +void +dk4dmt_error_fork_failed(dk4dmt_t *pdmt); + + +/** Set exit code in daemon structure to indicate setsid failed. + @param pdmt Daemon tool structure to use. +*/ + +void +dk4dmt_error_setsid(dk4dmt_t *pdmt); + + +/** Set exit code in daemon structure to indicate dup2 failed. + @param pdmt Daemon tool structure to use. +*/ + +void +dk4dmt_error_dup2_failed(dk4dmt_t *pdmt); + + +/** Set exit code in daemon structure to indicate reading /dev/null failed. + @param pdmt Daemon tool structure to use. +*/ + +void +dk4dmt_error_failed_read_dev_null(dk4dmt_t *pdmt); + + +/** Set exit code in daemon structure to indicate writing /dev/null failed. + @param pdmt Daemon tool structure to use. +*/ + +void +dk4dmt_error_failed_write_dev_null(dk4dmt_t *pdmt); + + +/** Set exit code in daemon structure to indicate chdir to / failed. + @param pdmt Daemon tool structure to use. +*/ + +void +dk4dmt_error_failed_chdir_root(dk4dmt_t *pdmt); + + +/** Set exit code in daemon structure for failed signal set cleanup. + @param pdmt Daemon tool structure to use. +*/ + void -dk4dmt_daemon_end(const char *prgname, const char *pidfilename, int slf); +dk4dmt_error_sigemptyset(dk4dmt_t *pdmt); + + +/** Set exit code in daemon structure for unusable configuration. + @param pdmt Daemon tool structure to use. +*/ + +void +dk4dmt_error_config(dk4dmt_t *pdmt); + + +/** Set exit code in daemon structure to indicate wrong call arguments. + @param pdmt Daemon tool structure to use. +*/ + +void +dk4dmt_error_usage(dk4dmt_t *pdmt); + + +/** Indicate success. + @param pdmt Daemon tool structure to use. +*/ +void +dk4dmt_success(dk4dmt_t *pdmt); + + +/** Retrieve exit status code. + @param pdmt Daemon tool structure to use. + @return Exit status code to return. +*/ + +int +dk4dmt_get_exit_status(dk4dmt_t *pdmt); -#ifdef __cplusplus +#ifdef __cplusplus } #endif |