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 #include "config.h"
26
27 #ifdef HAVE_STDIO_H
28 #include <stdio.h>
29 #endif
30
31 #ifdef HAVE_STDLIB_H
32 #include <stdlib.h>
33 #endif
34
35 #ifdef HAVE_ERRNO_H
36 #include <errno.h>
37 #endif
38
39 #ifdef HAVE_STRING_H
40 #include <string.h>
41 #endif
42
43 #ifdef HAVE_STRINGS_H
44 #include <strings.h>
45 #endif
46
47 #ifdef HAVE_SYS_TYPES_H
48 #include <sys/types.h>
49 #endif
50
51 #ifdef HAVE_SYS_STAT_H
52 #include <sys/stat.h>
53 #endif
54
55 #ifdef HAVE_UNISTD_H
56 #include <unistd.h>
57 #endif
58
59 #ifdef HAVE_FCNTL_H
60 #include <fcntl.h>
61 #endif
62
63 #ifdef HAVE_DIRENT_H
64 #include <dirent.h>
65 #endif
66
67 #include "monit.h"
68 #include "engine.h"
69
70 // libmonit
71 #include "io/File.h"
72
73 /**
74 * Utilities for managing files used by monit.
75 *
76 * @file
77 */
78
79
80 /* ------------------------------------------------------------------ Public */
81
82
file_init()83 void file_init() {
84 char pidfile[STRLEN];
85 char buf[STRLEN];
86 /* Check if the pidfile was already set during configfile parsing */
87 if (Run.files.pid == NULL) {
88 /* Set the location of this programs pidfile */
89 if (! getuid()) {
90 snprintf(pidfile, STRLEN, "%s/%s", MYPIDDIR, MYPIDFILE);
91 } else {
92 snprintf(pidfile, STRLEN, "%s/.%s", Run.Env.home, MYPIDFILE);
93 }
94 Run.files.pid = Str_dup(pidfile);
95 }
96 /* Set the location of monit's id file */
97 if (Run.files.id == NULL) {
98 snprintf(buf, STRLEN, "%s/.%s", Run.Env.home, MYIDFILE);
99 Run.files.id = Str_dup(buf);
100 }
101 Util_monitId(Run.files.id);
102 /* Set the location of monit's state file */
103 if (Run.files.state == NULL) {
104 snprintf(buf, STRLEN, "%s/.%s", Run.Env.home, MYSTATEFILE);
105 Run.files.state = Str_dup(buf);
106 }
107 }
108
109
file_finalize()110 void file_finalize() {
111 Engine_cleanup();
112 unlink(Run.files.pid);
113 }
114
115
file_findControlFile()116 char *file_findControlFile() {
117 char *rcfile = CALLOC(sizeof(char), STRLEN + 1);
118 snprintf(rcfile, STRLEN, "%s/.%s", Run.Env.home, MONITRC);
119 if (File_exist(rcfile)) {
120 return rcfile;
121 }
122 snprintf(rcfile, STRLEN, "/etc/%s", MONITRC);
123 if (File_exist(rcfile)) {
124 return rcfile;
125 }
126 snprintf(rcfile, STRLEN, "%s/%s", SYSCONFDIR, MONITRC);
127 if (File_exist(rcfile)) {
128 return rcfile;
129 }
130 snprintf(rcfile, STRLEN, "/usr/local/etc/%s", MONITRC);
131 if (File_exist(rcfile)) {
132 return rcfile;
133 }
134 if (File_exist(MONITRC)) {
135 snprintf(rcfile, STRLEN, "%s/%s", Run.Env.cwd, MONITRC);
136 return rcfile;
137 }
138 Log_error("Cannot find the Monit control file at ~/.%s, /etc/%s, %s/%s, /usr/local/etc/%s or at ./%s \n", MONITRC, MONITRC, SYSCONFDIR, MONITRC, MONITRC, MONITRC);
139 exit(1);
140 }
141
142
file_createPidFile(const char * pidfile)143 bool file_createPidFile(const char *pidfile) {
144 ASSERT(pidfile);
145 unlink(pidfile);
146 FILE *F = fopen(pidfile, "w");
147 if (! F) {
148 Log_error("Error opening pidfile '%s' for writing -- %s\n", pidfile, STRERROR);
149 return false;
150 }
151 fprintf(F, "%d\n", (int)getpid());
152 fclose(F);
153 return true;
154 }
155
156
file_checkStat(const char * filename,const char * description,mode_t permmask)157 bool file_checkStat(const char *filename, const char *description, mode_t permmask) {
158 ASSERT(filename);
159 ASSERT(description);
160 errno = 0;
161 struct stat buf;
162 if (stat(filename, &buf) < 0) {
163 Log_error("Cannot stat the %s '%s' -- %s\n", description, filename, STRERROR);
164 return false;
165 }
166 if (! S_ISREG(buf.st_mode)) {
167 Log_error("The %s '%s' is not a regular file.\n", description, filename);
168 return false;
169 }
170 if (buf.st_uid != geteuid()) {
171 Log_error("The %s '%s' must be owned by you.\n", description, filename);
172 return false;
173 }
174 if ((buf.st_mode & 0777) & ~permmask) {
175 Log_error("The %s '%s' permission 0%o is wrong, maximum 0%o allowed\n", description, filename, buf.st_mode & 0777, permmask & 0777);
176 return false;
177 }
178 return true;
179 }
180
181
file_checkQueueDirectory(const char * path)182 bool file_checkQueueDirectory(const char *path) {
183 if (mkdir(path, 0700) < 0 && errno != EEXIST) {
184 Log_error("Cannot create the event queue directory '%s' -- %s\n", path, STRERROR);
185 return false;
186 }
187 return true;
188 }
189
190
file_checkQueueLimit(const char * path,int limit)191 bool file_checkQueueLimit(const char *path, int limit) {
192 if (limit >= 0) {
193 DIR *dir = opendir(path);
194 if (! dir) {
195 Log_error("Cannot open the event queue directory '%s' -- %s\n", path, STRERROR);
196 return false;
197 }
198 int used = 0;
199 struct dirent *de = NULL;
200 while ((de = readdir(dir)) ) {
201 char buf[PATH_MAX];
202 snprintf(buf, sizeof(buf), "%s/%s", path, de->d_name);
203 if (File_isFile(buf) && ++used > limit) {
204 Log_error("Event queue is full\n");
205 closedir(dir);
206 return false;
207 }
208 }
209 closedir(dir);
210 }
211 return true;
212 }
213
214
file_writeQueue(FILE * file,const void * data,size_t size)215 bool file_writeQueue(FILE *file, const void *data, size_t size) {
216 ASSERT(file);
217 /* write size */
218 size_t rv = fwrite(&size, 1, sizeof(size_t), file);
219 if (rv != sizeof(size_t)) {
220 if (feof(file) || ferror(file))
221 Log_error("Queued event file: unable to write event size -- %s\n", feof(file) ? "end of file" : "stream error");
222 else
223 Log_error("Queued event file: unable to write event size -- read returned %lu bytes\n", (unsigned long)rv);
224 return false;
225 }
226 /* write data if any */
227 if (size > 0) {
228 if ((rv = fwrite(data, 1, size, file)) != size) {
229 if (feof(file) || ferror(file))
230 Log_error("Queued event file: unable to write event size -- %s\n", feof(file) ? "end of file" : "stream error");
231 else
232 Log_error("Queued event file: unable to write event size -- read returned %lu bytes\n", (unsigned long)rv);
233 return false;
234 }
235 }
236 return true;
237 }
238
239
file_readQueue(FILE * file,size_t * size)240 void *file_readQueue(FILE *file, size_t *size) {
241 ASSERT(file);
242 /* read size */
243 size_t rv = fread(size, 1, sizeof(size_t), file);
244 if (rv != sizeof(size_t)) {
245 if (feof(file) || ferror(file))
246 Log_error("Queued event file: unable to read event size -- %s\n", feof(file) ? "end of file" : "stream error");
247 else
248 Log_error("Queued event file: unable to read event size -- read returned %lu bytes\n", (unsigned long)rv);
249 return NULL;
250 }
251 /* read data if any (allow 1MB at maximum to prevent enormous memory allocation) */
252 void *data = NULL;
253 if (*size > 0 && *size < 1048576) {
254 data = CALLOC(1, *size);
255 if ((rv = fread(data, 1, *size, file)) != *size) {
256 FREE(data);
257 if (feof(file) || ferror(file))
258 Log_error("Queued event file: unable to read event data -- %s\n", feof(file) ? "end of file" : "stream error");
259 else
260 Log_error("Queued event file: unable to read event data -- read returned %lu bytes\n", (unsigned long)rv);
261 return NULL;
262 }
263 }
264 return data;
265 }
266
267
file_readProc(char * buf,int buf_size,const char * name,int pid,int * bytes_read)268 bool file_readProc(char *buf, int buf_size, const char *name, int pid, int *bytes_read) {
269 ASSERT(buf);
270 ASSERT(name);
271
272 char filename[STRLEN];
273 if (pid < 0)
274 snprintf(filename, sizeof(filename), "/proc/%s", name);
275 else
276 snprintf(filename, sizeof(filename), "/proc/%d/%s", pid, name);
277
278 int fd = open(filename, O_RDONLY);
279 if (fd < 0) {
280 if (Run.debug >= 2)
281 DEBUG("Cannot open proc file '%s' -- %s\n", filename, STRERROR);
282 return false;
283 }
284
285 bool rv = false;
286 int bytes = (int)read(fd, buf, buf_size - 1);
287 if (bytes >= 0) {
288 if (bytes_read)
289 *bytes_read = bytes;
290 buf[bytes] = 0;
291 rv = true;
292 } else {
293 *buf = 0;
294 DEBUG("Cannot read proc file '%s' -- %s\n", filename, STRERROR);
295 }
296
297 if (close(fd) < 0)
298 Log_error("Failed to close proc file '%s' -- %s\n", filename, STRERROR);
299
300 return rv;
301 }
302
303