summaryrefslogtreecommitdiffstats
path: root/lib/utils_cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/utils_cmd.c')
-rw-r--r--lib/utils_cmd.c41
1 files changed, 23 insertions, 18 deletions
diff --git a/lib/utils_cmd.c b/lib/utils_cmd.c
index 8b8e5708..cfb2073c 100644
--- a/lib/utils_cmd.c
+++ b/lib/utils_cmd.c
@@ -18,18 +18,18 @@
18* Care has been taken to make sure the functions are async-safe. The one 18* Care has been taken to make sure the functions are async-safe. The one
19* function which isn't is cmd_init() which it doesn't make sense to 19* function which isn't is cmd_init() which it doesn't make sense to
20* call twice anyway, so the api as a whole should be considered async-safe. 20* call twice anyway, so the api as a whole should be considered async-safe.
21* 21*
22* 22*
23* This program is free software: you can redistribute it and/or modify 23* This program is free software: you can redistribute it and/or modify
24* it under the terms of the GNU General Public License as published by 24* it under the terms of the GNU General Public License as published by
25* the Free Software Foundation, either version 3 of the License, or 25* the Free Software Foundation, either version 3 of the License, or
26* (at your option) any later version. 26* (at your option) any later version.
27* 27*
28* This program is distributed in the hope that it will be useful, 28* This program is distributed in the hope that it will be useful,
29* but WITHOUT ANY WARRANTY; without even the implied warranty of 29* but WITHOUT ANY WARRANTY; without even the implied warranty of
30* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31* GNU General Public License for more details. 31* GNU General Public License for more details.
32* 32*
33* You should have received a copy of the GNU General Public License 33* You should have received a copy of the GNU General Public License
34* along with this program. If not, see <http://www.gnu.org/licenses/>. 34* along with this program. If not, see <http://www.gnu.org/licenses/>.
35* 35*
@@ -42,7 +42,20 @@
42#include "common.h" 42#include "common.h"
43#include "utils.h" 43#include "utils.h"
44#include "utils_cmd.h" 44#include "utils_cmd.h"
45/* This variable must be global, since there's no way the caller
46 * can forcibly slay a dead or ungainly running program otherwise.
47 * Multithreading apps and plugins can initialize it (via CMD_INIT)
48 * in an async safe manner PRIOR to calling cmd_run() or cmd_run_array()
49 * for the first time.
50 *
51 * The check for initialized values is atomic and can
52 * occur in any number of threads simultaneously. */
53static pid_t *_cmd_pids = NULL;
54
45#include "utils_base.h" 55#include "utils_base.h"
56
57#include "./maxfd.h"
58
46#include <fcntl.h> 59#include <fcntl.h>
47 60
48#ifdef HAVE_SYS_WAIT_H 61#ifdef HAVE_SYS_WAIT_H
@@ -86,13 +99,7 @@ extern void die (int, const char *, ...)
86void 99void
87cmd_init (void) 100cmd_init (void)
88{ 101{
89#ifndef maxfd 102 long maxfd = mp_open_max();
90 if (!maxfd && (maxfd = sysconf (_SC_OPEN_MAX)) < 0) {
91 /* possibly log or emit a warning here, since there's no
92 * guarantee that our guess at maxfd will be adequate */
93 maxfd = DEFAULT_MAXFD;
94 }
95#endif
96 103
97 /* if maxfd is unnaturally high, we force it to a lower value 104 /* if maxfd is unnaturally high, we force it to a lower value
98 * ( e.g. on SunOS, when ulimit is set to unlimited: 2147483647 this would cause 105 * ( e.g. on SunOS, when ulimit is set to unlimited: 2147483647 this would cause
@@ -118,10 +125,6 @@ _cmd_open (char *const *argv, int *pfd, int *pfderr)
118 125
119 int i = 0; 126 int i = 0;
120 127
121 /* if no command was passed, return with no error */
122 if (argv == NULL)
123 return -1;
124
125 if (!_cmd_pids) 128 if (!_cmd_pids)
126 CMD_INIT; 129 CMD_INIT;
127 130
@@ -152,6 +155,7 @@ _cmd_open (char *const *argv, int *pfd, int *pfderr)
152 /* close all descriptors in _cmd_pids[] 155 /* close all descriptors in _cmd_pids[]
153 * This is executed in a separate address space (pure child), 156 * This is executed in a separate address space (pure child),
154 * so we don't have to worry about async safety */ 157 * so we don't have to worry about async safety */
158 long maxfd = mp_open_max();
155 for (i = 0; i < maxfd; i++) 159 for (i = 0; i < maxfd; i++)
156 if (_cmd_pids[i] > 0) 160 if (_cmd_pids[i] > 0)
157 close (i); 161 close (i);
@@ -178,6 +182,7 @@ _cmd_close (int fd)
178 pid_t pid; 182 pid_t pid;
179 183
180 /* make sure the provided fd was opened */ 184 /* make sure the provided fd was opened */
185 long maxfd = mp_open_max();
181 if (fd < 0 || fd > maxfd || !_cmd_pids || (pid = _cmd_pids[fd]) == 0) 186 if (fd < 0 || fd > maxfd || !_cmd_pids || (pid = _cmd_pids[fd]) == 0)
182 return -1; 187 return -1;
183 188
@@ -269,7 +274,6 @@ _cmd_fetch_output (int fd, output * op, int flags)
269int 274int
270cmd_run (const char *cmdstring, output * out, output * err, int flags) 275cmd_run (const char *cmdstring, output * out, output * err, int flags)
271{ 276{
272 int fd, pfd_out[2], pfd_err[2];
273 int i = 0, argc; 277 int i = 0, argc;
274 size_t cmdlen; 278 size_t cmdlen;
275 char **argv = NULL; 279 char **argv = NULL;
@@ -373,10 +377,10 @@ cmd_file_read ( char *filename, output *out, int flags)
373 if ((fd = open(filename, O_RDONLY)) == -1) { 377 if ((fd = open(filename, O_RDONLY)) == -1) {
374 die( STATE_UNKNOWN, _("Error opening %s: %s"), filename, strerror(errno) ); 378 die( STATE_UNKNOWN, _("Error opening %s: %s"), filename, strerror(errno) );
375 } 379 }
376 380
377 if(out) 381 if(out)
378 out->lines = _cmd_fetch_output (fd, out, flags); 382 out->lines = _cmd_fetch_output (fd, out, flags);
379 383
380 if (close(fd) == -1) 384 if (close(fd) == -1)
381 die( STATE_UNKNOWN, _("Error closing %s: %s"), filename, strerror(errno) ); 385 die( STATE_UNKNOWN, _("Error closing %s: %s"), filename, strerror(errno) );
382 386
@@ -391,6 +395,7 @@ timeout_alarm_handler (int signo)
391 printf (_("%s - Plugin timed out after %d seconds\n"), 395 printf (_("%s - Plugin timed out after %d seconds\n"),
392 state_text(timeout_state), timeout_interval); 396 state_text(timeout_state), timeout_interval);
393 397
398 long maxfd = mp_open_max();
394 if(_cmd_pids) for(i = 0; i < maxfd; i++) { 399 if(_cmd_pids) for(i = 0; i < maxfd; i++) {
395 if(_cmd_pids[i] != 0) kill(_cmd_pids[i], SIGKILL); 400 if(_cmd_pids[i] != 0) kill(_cmd_pids[i], SIGKILL);
396 } 401 }