1 /*
2 * Copyright (C) Tildeslash Ltd. All rights reserved.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License version 3.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU Affero General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *
15 * In addition, as a special exception, the copyright holders give
16 * permission to link the code of portions of this program with the
17 * OpenSSL library under certain conditions as described in each
18 * individual source file, and distribute linked combinations
19 * including the two.
20 *
21 * You must obey the GNU Affero General Public License in all respects
22 * for all of the code used other than OpenSSL.
23 */
24
25
26 #include "config.h"
27
28 #ifdef HAVE_STDIO_H
29 #include <stdio.h>
30 #endif
31
32 #ifdef HAVE_STDLIB_H
33 #include <stdlib.h>
34 #endif
35
36 #ifdef HAVE_ERRNO_H
37 #include <errno.h>
38 #endif
39
40 #ifdef HAVE_SIGNAL_H
41 #include <signal.h>
42 #endif
43
44 #ifdef HAVE_UNISTD_H
45 #include <unistd.h>
46 #endif
47
48 #ifdef HAVE_SYS_TYPES_H
49 #include <sys/types.h>
50 #endif
51
52 #ifdef HAVE_SYS_STAT_H
53 #include <sys/stat.h>
54 #endif
55
56 #ifdef HAVE_FCNTL_H
57 #include <fcntl.h>
58 #endif
59
60 #ifdef HAVE_STRING_H
61 #include <string.h>
62 #endif
63
64 #include "monit.h"
65
66
67 /**
68 * Transform this program into a daemon and provide methods for
69 * managing the daemon.
70 *
71 * @file
72 */
73
74
75 /* ------------------------------------------------------------------ Public */
76
77
78 /**
79 * Transform a program into a daemon. Inspired by code from Stephen
80 * A. Rago's book, Unix System V Network Programming.
81 */
daemonize()82 void daemonize() {
83 pid_t pid;
84 /*
85 * Become a session leader to lose our controlling terminal
86 */
87 if ((pid = fork ()) < 0) {
88 Log_error("Cannot fork a new process\n");
89 exit (1);
90 } else if (pid != 0) {
91 _exit(0);
92 }
93 setsid();
94 if ((pid = fork ()) < 0) {
95 Log_error("Cannot fork a new process\n");
96 exit (1);
97 } else if (pid != 0) {
98 _exit(0);
99 }
100 /*
101 * Change current directory to the root so that other file systems can be unmounted while we're running
102 */
103 if (chdir("/") < 0) {
104 Log_error("Cannot chdir to / -- %s\n", STRERROR);
105 exit(1);
106 }
107 /*
108 * Attach standard descriptors to /dev/null. Other descriptors should be closed in env.c
109 */
110 Util_redirectStdFds();
111 }
112
113
114 /**
115 * Send signal to a daemon process
116 * @param sig Signal to send daemon to
117 * @return true if signal was send, otherwise false
118 */
kill_daemon(int sig)119 bool kill_daemon(int sig) {
120 pid_t pid;
121 if ((pid = exist_daemon()) > 0) {
122 if (kill(pid, sig) < 0) {
123 Log_error("Cannot signal the monit daemon process -- %s\n", STRERROR);
124 return false;
125 }
126 } else {
127 Log_info("Monit daemon is not running\n");
128 return true;
129 }
130 if (sig == SIGTERM) {
131 fprintf(stdout, "Monit daemon with pid [%d] killed\n", (int)pid);
132 fflush(stdout);
133 }
134 return true;
135 }
136
137
138 /**
139 * @return true (i.e. the daemons pid) if a daemon process is running,
140 * otherwise false
141 */
exist_daemon()142 int exist_daemon() {
143 errno = 0;
144 pid_t pid;
145 if ((pid = Util_getPid(Run.files.pid)) && (getpgid(pid) > -1 || errno == EPERM))
146 return (int)pid;
147 return 0;
148 }
149
150