23 #include <core/exception.h> 36 # include <libdaemon/dfork.h> 37 # include <libdaemon/dlog.h> 38 # include <libdaemon/dpid.h> 39 # include <sys/stat.h> 40 # include <sys/wait.h> 44 bool g_force_quit =
false;
45 int g_signum = SIGINT;
48 handle_signal(
int signum)
50 printf(
"Received %s signal\n", strsignal(signum));
53 case SIGINT: g_quit += 1;
break;
54 case SIGTERM: g_quit = 3;
break;
55 case SIGKILL: g_quit = 4;
break;
64 usage(
const char *progname)
66 printf(
"Usage: %s [options] <progfile> [args...]\n" 67 "progfile full absolute path to executable\n" 68 "args any number of arguments, passed to program as-is\n\n" 69 "where [options] passed in before <progfile> are one or more of:\n" 71 " -D[pid file] Run daemonized in the background, pid file is optional,\n" 72 " defaults to /var/run/ffwatchdog_basename.pid, must be absolute path.\n" 73 " -D[pid file] -k Kill a daemonized process running in the background,\n" 74 " pid file is optional as above.\n" 75 " -D[pid file] -s Check status of daemon.\n" 77 " -h Show help instructions.\n\n",
83 fork_and_exec(
int argc,
char **argv,
int prog_start)
88 printf(
"Forking for new process failed: %s\n", strerror(errno));
90 }
else if (pid == 0) {
93 signal(SIGINT, SIG_IGN);
94 if (execve(argv[prog_start], &argv[prog_start], environ) == -1) {
95 printf(
"Failed to execute %s, exited with %i: %s\n",
96 argv[prog_start], errno, strerror(errno));
105 #ifdef HAVE_LIBDAEMON 109 daemon_retval_send(-1);
110 daemon_retval_done();
111 daemon_pid_file_remove();}
114 daemonize(
int argc,
char **argv)
117 mode_t old_umask = umask(0);
120 daemon_retval_init();
123 if ((pid = daemon_fork()) < 0) {
130 if ((ret = daemon_retval_wait(20)) < 0) {
131 daemon_log(LOG_ERR,
"Could not recieve return value from daemon process.");
136 daemon_log(LOG_ERR,
"*** Daemon startup failed, see syslog for details. ***");
139 daemon_log(LOG_ERR,
"Daemon failed to close file descriptors");
142 daemon_log(LOG_ERR,
"Daemon failed to create PID file");
151 #ifdef DAEMON_CLOSE_ALL_AVAILABLE 152 if (daemon_close_all(-1) < 0) {
153 daemon_log(LOG_ERR,
"Failed to close all file descriptors: %s",
156 daemon_retval_send(1);
162 if (daemon_pid_file_create() < 0) {
163 printf(
"Could not create PID file (%s).", strerror(errno));
164 daemon_log(LOG_ERR,
"Could not create PID file (%s).", strerror(errno));
167 daemon_retval_send(2);
172 daemon_retval_send(0);
174 daemon_log(LOG_INFO,
"Sucessfully started");
183 const char *ffwatchdog_pid_file;
189 ffwatchdog_daemon_pid_file_proc()
191 return ffwatchdog_pid_file;
193 #endif // HAVE_LIBDAEMON 202 main(
int argc,
char **argv)
209 bool arg_verbose =
false;
210 bool arg_daemonize =
false;
211 bool arg_daemon_kill =
false;
212 bool arg_daemon_status =
false;
213 const char *daemon_pid_file = NULL;
216 for (prog_start = 1; prog_start < argc; ++prog_start) {
217 if (argv[prog_start][0] ==
'-') {
219 char param = argv[prog_start][1];
225 arg_daemonize =
true;
226 daemon_pid_file = NULL;
227 if (strlen(&argv[prog_start][1]) > 1) {
228 daemon_pid_file = &argv[prog_start][2];
230 }
else if (param ==
'k') {
231 arg_daemon_kill =
true;
232 }
else if (param ==
's') {
233 arg_daemon_status =
true;
234 }
else if (param ==
'v') {
236 }
else if (param ==
'h') {
240 printf(
"Unknown argument '%c'\n", param);
250 if (prog_start >= argc) {
255 if (access(argv[prog_start], X_OK) != 0) {
256 printf(
"Cannot execute '%s': %s\n\n", argv[1], strerror(errno));
261 #ifdef HAVE_LIBDAEMON 265 char *daemon_ident = NULL;
267 if ( arg_daemonize ) {
270 char *argv_copy = strdup(argv[prog_start]);
271 if (asprintf(&daemon_ident,
"ffwatchdog_%s", basename(argv_copy)) == -1) {
273 printf(
"Failed to create daemon ident, not enough memory\n");
277 daemon_pid_file_ident = daemon_log_ident = daemon_ident;
278 if ( daemon_pid_file != NULL ) {
279 ffwatchdog_pid_file = daemon_pid_file;
280 daemon_pid_file_proc = ffwatchdog_daemon_pid_file_proc;
284 if (arg_daemon_kill) {
286 if ((dpid = daemon_pid_file_is_running()) < 0) {
287 daemon_log(LOG_ERR,
"Watchdog daemon for %s not running.",
293 if ((ret = daemon_pid_file_kill_wait(SIGINT, 5)) < 0) {
294 daemon_log(LOG_WARNING,
"Failed to kill watchdog daemon for %s",
297 return (ret < 0) ? 1 : 0;
300 if (arg_daemon_status) {
302 if (daemon_pid_file_is_running() < 0) {
304 printf(
"Watchdog daemon for %s is not running\n", argv[prog_start]);
309 printf(
"Watchdog daemon for %s is running\n", argv[prog_start]);
316 if ((dpid = daemon_pid_file_is_running()) >= 0) {
317 daemon_log(LOG_ERR,
"Watchdog daemon for %s already running on (PID %u)",
318 argv[prog_start], dpid);
322 dpid = daemonize(argc, argv);
333 printf(
"Daemonize support was not available at compile time.\n");
339 sa.sa_handler = handle_signal;
340 sigemptyset(&sa.sa_mask);
342 sigaction(SIGINT, &sa, NULL);
343 sigaction(SIGKILL, &sa, NULL);
344 sigaction(SIGTERM, &sa, NULL);
345 sigaction(SIGUSR1, &sa, NULL);
346 sigaction(SIGUSR2, &sa, NULL);
350 pid = fork_and_exec(argc, argv, prog_start);
352 while (pid != -1 && ! g_quit) {
355 pid_t cpid = waitpid(pid, &status, WUNTRACED | WCONTINUED);
356 printf(
"Wait returned\n");
359 printf(
"Failed to wait for child: %s\n", strerror(errno));
360 }
else if (WIFEXITED(status)) {
361 printf(
"%i|%s exited, status=%d\n", cpid, argv[prog_start],
362 WEXITSTATUS(status));
364 }
else if (WIFSIGNALED(status)) {
365 printf(
"%i|%s killed by signal %s\n", cpid, argv[prog_start],
366 strsignal(WTERMSIG(status)));
368 }
else if (WIFSTOPPED(status)) {
369 printf(
"%i|%s stopped by signal %s\n", cpid, argv[prog_start],
370 strsignal(WSTOPSIG(status)));
372 }
else if (WIFCONTINUED(status)) {
373 printf(
"%i|%s continued\n", cpid, argv[prog_start]);
381 printf(
"Stopping child. Press Ctrl-C again to escalate.\n");
383 for (
unsigned int i = 0; i < 600; ++i) {
384 if (last_quit != g_quit) {
388 }
else if (g_quit == 3) {
394 printf(
"Killing %s with signal %s\n", argv[prog_start],
396 if (kill(pid, signum) == -1) {
397 printf(
"Failed to kill %s: %s\n", argv[prog_start], strerror(errno));
404 int rv = waitpid(pid, &status, WNOHANG);
406 if (errno == EINTR)
continue;
407 if (errno == ECHILD) {
415 if (i >= 300) g_quit = 2;
416 if (i >= 500) g_quit = 3;
420 #ifdef HAVE_LIBDAEMON Base class for exceptions in Fawkes.