00001 /*** 00002 This file is part of libdaemon. 00003 00004 Copyright 2003-2008 Lennart Poettering 00005 00006 libdaemon is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU Lesser General Public License as 00008 published by the Free Software Foundation, either version 2.1 of the 00009 License, or (at your option) any later version. 00010 00011 libdaemon is distributed in the hope that it will be useful, but 00012 WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Lesser General Public License for more details. 00015 00016 You should have received a copy of the GNU Lesser General Public 00017 License along with libdaemon. If not, see 00018 <http://www.gnu.org/licenses/>. 00019 ***/ 00020 00021 #include <signal.h> 00022 #include <errno.h> 00023 #include <string.h> 00024 #include <sys/types.h> 00025 #include <sys/time.h> 00026 #include <sys/unistd.h> 00027 #include <sys/select.h> 00028 00029 #include <libdaemon/dfork.h> 00030 #include <libdaemon/dsignal.h> 00031 #include <libdaemon/dlog.h> 00032 #include <libdaemon/dpid.h> 00033 #include <libdaemon/dexec.h> 00034 00035 int main(int argc, char *argv[]) { 00036 pid_t pid; 00037 00038 /* Reset signal handlers */ 00039 if (daemon_reset_sigs(-1) < 0) { 00040 daemon_log(LOG_ERR, "Failed to reset all signal handlers: %s", strerror(errno)); 00041 return 1; 00042 } 00043 00044 /* Unblock signals */ 00045 if (daemon_unblock_sigs(-1) < 0) { 00046 daemon_log(LOG_ERR, "Failed to unblock all signals: %s", strerror(errno)); 00047 return 1; 00048 } 00049 00050 /* Set indetification string for the daemon for both syslog and PID file */ 00051 daemon_pid_file_ident = daemon_log_ident = daemon_ident_from_argv0(argv[0]); 00052 00053 /* Check if we are called with -k parameter */ 00054 if (argc >= 2 && !strcmp(argv[1], "-k")) { 00055 int ret; 00056 00057 /* Kill daemon with SIGINT */ 00058 00059 /* Check if the new function daemon_pid_file_kill_wait() is available, if it is, use it. */ 00060 if ((ret = daemon_pid_file_kill_wait(SIGINT, 5)) < 0) 00061 daemon_log(LOG_WARNING, "Failed to kill daemon: %s", strerror(errno)); 00062 00063 return ret < 0 ? 1 : 0; 00064 } 00065 00066 /* Check that the daemon is not rung twice a the same time */ 00067 if ((pid = daemon_pid_file_is_running()) >= 0) { 00068 daemon_log(LOG_ERR, "Daemon already running on PID file %u", pid); 00069 return 1; 00070 } 00071 00072 /* Prepare for return value passing from the initialization procedure of the daemon process */ 00073 daemon_retval_init(); 00074 00075 /* Do the fork */ 00076 if ((pid = daemon_fork()) < 0) { 00077 00078 /* Exit on error */ 00079 daemon_retval_done(); 00080 return 1; 00081 00082 } else if (pid) { /* The parent */ 00083 int ret; 00084 00085 /* Wait for 20 seconds for the return value passed from the daemon process */ 00086 if ((ret = daemon_retval_wait(20)) < 0) { 00087 daemon_log(LOG_ERR, "Could not recieve return value from daemon process: %s", strerror(errno)); 00088 return 255; 00089 } 00090 00091 daemon_log(ret != 0 ? LOG_ERR : LOG_INFO, "Daemon returned %i as return value.", ret); 00092 return ret; 00093 00094 } else { /* The daemon */ 00095 int fd, quit = 0; 00096 fd_set fds; 00097 00098 /* Close FDs */ 00099 if (daemon_close_all(-1) < 0) { 00100 daemon_log(LOG_ERR, "Failed to close all file descriptors: %s", strerror(errno)); 00101 00102 /* Send the error condition to the parent process */ 00103 daemon_retval_send(1); 00104 goto finish; 00105 } 00106 00107 /* Create the PID file */ 00108 if (daemon_pid_file_create() < 0) { 00109 daemon_log(LOG_ERR, "Could not create PID file (%s).", strerror(errno)); 00110 daemon_retval_send(2); 00111 goto finish; 00112 } 00113 00114 /* Initialize signal handling */ 00115 if (daemon_signal_init(SIGINT, SIGTERM, SIGQUIT, SIGHUP, 0) < 0) { 00116 daemon_log(LOG_ERR, "Could not register signal handlers (%s).", strerror(errno)); 00117 daemon_retval_send(3); 00118 goto finish; 00119 } 00120 00121 /*... do some further init work here */ 00122 00123 00124 /* Send OK to parent process */ 00125 daemon_retval_send(0); 00126 00127 daemon_log(LOG_INFO, "Sucessfully started"); 00128 00129 /* Prepare for select() on the signal fd */ 00130 FD_ZERO(&fds); 00131 fd = daemon_signal_fd(); 00132 FD_SET(fd, &fds); 00133 00134 while (!quit) { 00135 fd_set fds2 = fds; 00136 00137 /* Wait for an incoming signal */ 00138 if (select(FD_SETSIZE, &fds2, 0, 0, 0) < 0) { 00139 00140 /* If we've been interrupted by an incoming signal, continue */ 00141 if (errno == EINTR) 00142 continue; 00143 00144 daemon_log(LOG_ERR, "select(): %s", strerror(errno)); 00145 break; 00146 } 00147 00148 /* Check if a signal has been recieved */ 00149 if (FD_ISSET(fd, &fds)) { 00150 int sig; 00151 00152 /* Get signal */ 00153 if ((sig = daemon_signal_next()) <= 0) { 00154 daemon_log(LOG_ERR, "daemon_signal_next() failed: %s", strerror(errno)); 00155 break; 00156 } 00157 00158 /* Dispatch signal */ 00159 switch (sig) { 00160 00161 case SIGINT: 00162 case SIGQUIT: 00163 case SIGTERM: 00164 daemon_log(LOG_WARNING, "Got SIGINT, SIGQUIT or SIGTERM"); 00165 quit = 1; 00166 break; 00167 00168 case SIGHUP: 00169 daemon_log(LOG_INFO, "Got a HUP"); 00170 daemon_exec("/", NULL, "/bin/ls", "ls", (char*) NULL); 00171 break; 00172 00173 } 00174 } 00175 } 00176 00177 /* Do a cleanup */ 00178 finish: 00179 daemon_log(LOG_INFO, "Exiting..."); 00180 daemon_retval_send(255); 00181 daemon_signal_done(); 00182 daemon_pid_file_remove(); 00183 00184 return 0; 00185 } 00186 }