1/*** 2 This file is part of libdaemon. 3 4 Copyright 2003-2008 Lennart Poettering 5 6 libdaemon is free software; you can redistribute it and/or modify 7 it under the terms of the GNU Lesser General Public License as 8 published by the Free Software Foundation, either version 2.1 of the 9 License, or (at your option) any later version. 10 11 libdaemon is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with libdaemon. If not, see 18 <http://www.gnu.org/licenses/>. 19***/ 20 21#include <signal.h> 22#include <errno.h> 23#include <string.h> 24#include <sys/types.h> 25#include <sys/time.h> 26#include <sys/unistd.h> 27#include <sys/select.h> 28 29#include <libdaemon/dfork.h> 30#include <libdaemon/dsignal.h> 31#include <libdaemon/dlog.h> 32#include <libdaemon/dpid.h> 33#include <libdaemon/dexec.h> 34 35int main(int argc, char *argv[]) { 36 pid_t pid; 37 38 /* Reset signal handlers */ 39 if (daemon_reset_sigs(-1) < 0) { 40 daemon_log(LOG_ERR, "Failed to reset all signal handlers: %s", strerror(errno)); 41 return 1; 42 } 43 44 /* Unblock signals */ 45 if (daemon_unblock_sigs(-1) < 0) { 46 daemon_log(LOG_ERR, "Failed to unblock all signals: %s", strerror(errno)); 47 return 1; 48 } 49 50 /* Set indetification string for the daemon for both syslog and PID file */ 51 daemon_pid_file_ident = daemon_log_ident = daemon_ident_from_argv0(argv[0]); 52 53 /* Check if we are called with -k parameter */ 54 if (argc >= 2 && !strcmp(argv[1], "-k")) { 55 int ret; 56 57 /* Kill daemon with SIGTERM */ 58 59 /* Check if the new function daemon_pid_file_kill_wait() is available, if it is, use it. */ 60 if ((ret = daemon_pid_file_kill_wait(SIGTERM, 5)) < 0) 61 daemon_log(LOG_WARNING, "Failed to kill daemon: %s", strerror(errno)); 62 63 return ret < 0 ? 1 : 0; 64 } 65 66 /* Check that the daemon is not rung twice a the same time */ 67 if ((pid = daemon_pid_file_is_running()) >= 0) { 68 daemon_log(LOG_ERR, "Daemon already running on PID file %u", pid); 69 return 1; 70 } 71 72 /* Prepare for return value passing from the initialization procedure of the daemon process */ 73 if (daemon_retval_init() < 0) { 74 daemon_log(LOG_ERR, "Failed to create pipe."); 75 return 1; 76 } 77 78 /* Do the fork */ 79 if ((pid = daemon_fork()) < 0) { 80 81 /* Exit on error */ 82 daemon_retval_done(); 83 return 1; 84 85 } else if (pid) { /* The parent */ 86 int ret; 87 88 /* Wait for 20 seconds for the return value passed from the daemon process */ 89 if ((ret = daemon_retval_wait(20)) < 0) { 90 daemon_log(LOG_ERR, "Could not recieve return value from daemon process: %s", strerror(errno)); 91 return 255; 92 } 93 94 daemon_log(ret != 0 ? LOG_ERR : LOG_INFO, "Daemon returned %i as return value.", ret); 95 return ret; 96 97 } else { /* The daemon */ 98 int fd, quit = 0; 99 fd_set fds; 100 101 /* Close FDs */ 102 if (daemon_close_all(-1) < 0) { 103 daemon_log(LOG_ERR, "Failed to close all file descriptors: %s", strerror(errno)); 104 105 /* Send the error condition to the parent process */ 106 daemon_retval_send(1); 107 goto finish; 108 } 109 110 /* Create the PID file */ 111 if (daemon_pid_file_create() < 0) { 112 daemon_log(LOG_ERR, "Could not create PID file (%s).", strerror(errno)); 113 daemon_retval_send(2); 114 goto finish; 115 } 116 117 /* Initialize signal handling */ 118 if (daemon_signal_init(SIGINT, SIGTERM, SIGQUIT, SIGHUP, 0) < 0) { 119 daemon_log(LOG_ERR, "Could not register signal handlers (%s).", strerror(errno)); 120 daemon_retval_send(3); 121 goto finish; 122 } 123 124 /*... do some further init work here */ 125 126 127 /* Send OK to parent process */ 128 daemon_retval_send(0); 129 130 daemon_log(LOG_INFO, "Sucessfully started"); 131 132 /* Prepare for select() on the signal fd */ 133 FD_ZERO(&fds); 134 fd = daemon_signal_fd(); 135 FD_SET(fd, &fds); 136 137 while (!quit) { 138 fd_set fds2 = fds; 139 140 /* Wait for an incoming signal */ 141 if (select(FD_SETSIZE, &fds2, 0, 0, 0) < 0) { 142 143 /* If we've been interrupted by an incoming signal, continue */ 144 if (errno == EINTR) 145 continue; 146 147 daemon_log(LOG_ERR, "select(): %s", strerror(errno)); 148 break; 149 } 150 151 /* Check if a signal has been recieved */ 152 if (FD_ISSET(fd, &fds2)) { 153 int sig; 154 155 /* Get signal */ 156 if ((sig = daemon_signal_next()) <= 0) { 157 daemon_log(LOG_ERR, "daemon_signal_next() failed: %s", strerror(errno)); 158 break; 159 } 160 161 /* Dispatch signal */ 162 switch (sig) { 163 164 case SIGINT: 165 case SIGQUIT: 166 case SIGTERM: 167 daemon_log(LOG_WARNING, "Got SIGINT, SIGQUIT or SIGTERM."); 168 quit = 1; 169 break; 170 171 case SIGHUP: 172 daemon_log(LOG_INFO, "Got a HUP"); 173 daemon_exec("/", NULL, "/bin/ls", "ls", (char*) NULL); 174 break; 175 176 } 177 } 178 } 179 180 /* Do a cleanup */ 181finish: 182 daemon_log(LOG_INFO, "Exiting..."); 183 daemon_retval_send(255); 184 daemon_signal_done(); 185 daemon_pid_file_remove(); 186 187 return 0; 188 } 189} 190