diff options
Diffstat (limited to 'examples')
-rw-r--r-- | examples/.gitignore | 2 | ||||
-rw-r--r-- | examples/Makefile.am | 28 | ||||
-rw-r--r-- | examples/testd.c | 194 |
3 files changed, 224 insertions, 0 deletions
diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 0000000..db50de7 --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1,2 @@ +testd + diff --git a/examples/Makefile.am b/examples/Makefile.am new file mode 100644 index 0000000..930c3bf --- /dev/null +++ b/examples/Makefile.am @@ -0,0 +1,28 @@ +# This file is part of libdaemon. +# +# Copyright 2003-2008 Lennart Poettering +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +noinst_PROGRAMS = testd + +AM_CPPFLAGS=-I$(top_srcdir) + +testd_SOURCES=testd.c +testd_LDADD=../libdaemon/libdaemon.la diff --git a/examples/testd.c b/examples/testd.c new file mode 100644 index 0000000..9154f7b --- /dev/null +++ b/examples/testd.c @@ -0,0 +1,194 @@ +/*** + This file is part of libdaemon. + + Copyright 2003-2008 Lennart Poettering + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +***/ + +#include <signal.h> +#include <errno.h> +#include <string.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/unistd.h> +#include <sys/select.h> + +#include <libdaemon/dfork.h> +#include <libdaemon/dsignal.h> +#include <libdaemon/dlog.h> +#include <libdaemon/dpid.h> +#include <libdaemon/dexec.h> + +int main(int argc, char *argv[]) { + pid_t pid; + + /* Reset signal handlers */ + if (daemon_reset_sigs(-1) < 0) { + daemon_log(LOG_ERR, "Failed to reset all signal handlers: %s", strerror(errno)); + return 1; + } + + /* Unblock signals */ + if (daemon_unblock_sigs(-1) < 0) { + daemon_log(LOG_ERR, "Failed to unblock all signals: %s", strerror(errno)); + return 1; + } + + /* Set indetification string for the daemon for both syslog and PID file */ + daemon_pid_file_ident = daemon_log_ident = daemon_ident_from_argv0(argv[0]); + + /* Check if we are called with -k parameter */ + if (argc >= 2 && !strcmp(argv[1], "-k")) { + int ret; + + /* Kill daemon with SIGTERM */ + + /* Check if the new function daemon_pid_file_kill_wait() is available, if it is, use it. */ + if ((ret = daemon_pid_file_kill_wait(SIGTERM, 5)) < 0) + daemon_log(LOG_WARNING, "Failed to kill daemon: %s", strerror(errno)); + + return ret < 0 ? 1 : 0; + } + + /* Check that the daemon is not rung twice a the same time */ + if ((pid = daemon_pid_file_is_running()) >= 0) { + daemon_log(LOG_ERR, "Daemon already running on PID file %u", pid); + return 1; + } + + /* Prepare for return value passing from the initialization procedure of the daemon process */ + if (daemon_retval_init() < 0) { + daemon_log(LOG_ERR, "Failed to create pipe."); + return 1; + } + + /* Do the fork */ + if ((pid = daemon_fork()) < 0) { + + /* Exit on error */ + daemon_retval_done(); + return 1; + + } else if (pid) { /* The parent */ + int ret; + + /* Wait for 20 seconds for the return value passed from the daemon process */ + if ((ret = daemon_retval_wait(20)) < 0) { + daemon_log(LOG_ERR, "Could not recieve return value from daemon process: %s", strerror(errno)); + return 255; + } + + daemon_log(ret != 0 ? LOG_ERR : LOG_INFO, "Daemon returned %i as return value.", ret); + return ret; + + } else { /* The daemon */ + int fd, quit = 0; + fd_set fds; + + /* Close FDs */ + if (daemon_close_all(-1) < 0) { + daemon_log(LOG_ERR, "Failed to close all file descriptors: %s", strerror(errno)); + + /* Send the error condition to the parent process */ + daemon_retval_send(1); + goto finish; + } + + /* Create the PID file */ + if (daemon_pid_file_create() < 0) { + daemon_log(LOG_ERR, "Could not create PID file (%s).", strerror(errno)); + daemon_retval_send(2); + goto finish; + } + + /* Initialize signal handling */ + if (daemon_signal_init(SIGINT, SIGTERM, SIGQUIT, SIGHUP, 0) < 0) { + daemon_log(LOG_ERR, "Could not register signal handlers (%s).", strerror(errno)); + daemon_retval_send(3); + goto finish; + } + + /*... do some further init work here */ + + + /* Send OK to parent process */ + daemon_retval_send(0); + + daemon_log(LOG_INFO, "Sucessfully started"); + + /* Prepare for select() on the signal fd */ + FD_ZERO(&fds); + fd = daemon_signal_fd(); + FD_SET(fd, &fds); + + while (!quit) { + fd_set fds2 = fds; + + /* Wait for an incoming signal */ + if (select(FD_SETSIZE, &fds2, 0, 0, 0) < 0) { + + /* If we've been interrupted by an incoming signal, continue */ + if (errno == EINTR) + continue; + + daemon_log(LOG_ERR, "select(): %s", strerror(errno)); + break; + } + + /* Check if a signal has been recieved */ + if (FD_ISSET(fd, &fds2)) { + int sig; + + /* Get signal */ + if ((sig = daemon_signal_next()) <= 0) { + daemon_log(LOG_ERR, "daemon_signal_next() failed: %s", strerror(errno)); + break; + } + + /* Dispatch signal */ + switch (sig) { + + case SIGINT: + case SIGQUIT: + case SIGTERM: + daemon_log(LOG_WARNING, "Got SIGINT, SIGQUIT or SIGTERM."); + quit = 1; + break; + + case SIGHUP: + daemon_log(LOG_INFO, "Got a HUP"); + daemon_exec("/", NULL, "/bin/ls", "ls", (char*) NULL); + break; + + } + } + } + + /* Do a cleanup */ +finish: + daemon_log(LOG_INFO, "Exiting..."); + daemon_retval_send(255); + daemon_signal_done(); + daemon_pid_file_remove(); + + return 0; + } +} |