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.c73
1 files changed, 35 insertions, 38 deletions
diff --git a/lib/utils_cmd.c b/lib/utils_cmd.c
index 7eb9a3a0..f66fd573 100644
--- a/lib/utils_cmd.c
+++ b/lib/utils_cmd.c
@@ -40,8 +40,22 @@
40 40
41/** includes **/ 41/** includes **/
42#include "common.h" 42#include "common.h"
43#include "utils.h"
43#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
44#include "utils_base.h" 55#include "utils_base.h"
56
57#include "./maxfd.h"
58
45#include <fcntl.h> 59#include <fcntl.h>
46 60
47#ifdef HAVE_SYS_WAIT_H 61#ifdef HAVE_SYS_WAIT_H
@@ -65,31 +79,6 @@ extern char **environ;
65# define SIG_ERR ((Sigfunc *)-1) 79# define SIG_ERR ((Sigfunc *)-1)
66#endif 80#endif
67 81
68/* This variable must be global, since there's no way the caller
69 * can forcibly slay a dead or ungainly running program otherwise.
70 * Multithreading apps and plugins can initialize it (via CMD_INIT)
71 * in an async safe manner PRIOR to calling cmd_run() or cmd_run_array()
72 * for the first time.
73 *
74 * The check for initialized values is atomic and can
75 * occur in any number of threads simultaneously. */
76static pid_t *_cmd_pids = NULL;
77
78/* Try sysconf(_SC_OPEN_MAX) first, as it can be higher than OPEN_MAX.
79 * If that fails and the macro isn't defined, we fall back to an educated
80 * guess. There's no guarantee that our guess is adequate and the program
81 * will die with SIGSEGV if it isn't and the upper boundary is breached. */
82#define DEFAULT_MAXFD 256 /* fallback value if no max open files value is set */
83#define MAXFD_LIMIT 8192 /* upper limit of open files */
84#ifdef _SC_OPEN_MAX
85static long maxfd = 0;
86#elif defined(OPEN_MAX)
87# define maxfd OPEN_MAX
88#else /* sysconf macro unavailable, so guess (may be wildly inaccurate) */
89# define maxfd DEFAULT_MAXFD
90#endif
91
92
93/** prototypes **/ 82/** prototypes **/
94static int _cmd_open (char *const *, int *, int *) 83static int _cmd_open (char *const *, int *, int *)
95 __attribute__ ((__nonnull__ (1, 2, 3))); 84 __attribute__ ((__nonnull__ (1, 2, 3)));
@@ -110,13 +99,7 @@ extern void die (int, const char *, ...)
110void 99void
111cmd_init (void) 100cmd_init (void)
112{ 101{
113#ifndef maxfd 102 long maxfd = mp_open_max();
114 if (!maxfd && (maxfd = sysconf (_SC_OPEN_MAX)) < 0) {
115 /* possibly log or emit a warning here, since there's no
116 * guarantee that our guess at maxfd will be adequate */
117 maxfd = DEFAULT_MAXFD;
118 }
119#endif
120 103
121 /* 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
122 * ( 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
@@ -142,10 +125,6 @@ _cmd_open (char *const *argv, int *pfd, int *pfderr)
142 125
143 int i = 0; 126 int i = 0;
144 127
145 /* if no command was passed, return with no error */
146 if (argv == NULL)
147 return -1;
148
149 if (!_cmd_pids) 128 if (!_cmd_pids)
150 CMD_INIT; 129 CMD_INIT;
151 130
@@ -176,6 +155,7 @@ _cmd_open (char *const *argv, int *pfd, int *pfderr)
176 /* close all descriptors in _cmd_pids[] 155 /* close all descriptors in _cmd_pids[]
177 * This is executed in a separate address space (pure child), 156 * This is executed in a separate address space (pure child),
178 * 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();
179 for (i = 0; i < maxfd; i++) 159 for (i = 0; i < maxfd; i++)
180 if (_cmd_pids[i] > 0) 160 if (_cmd_pids[i] > 0)
181 close (i); 161 close (i);
@@ -185,7 +165,7 @@ _cmd_open (char *const *argv, int *pfd, int *pfderr)
185 } 165 }
186 166
187 /* parent picks up execution here */ 167 /* parent picks up execution here */
188 /* close childs descriptors in our address space */ 168 /* close children descriptors in our address space */
189 close (pfd[1]); 169 close (pfd[1]);
190 close (pfderr[1]); 170 close (pfderr[1]);
191 171
@@ -202,6 +182,7 @@ _cmd_close (int fd)
202 pid_t pid; 182 pid_t pid;
203 183
204 /* make sure the provided fd was opened */ 184 /* make sure the provided fd was opened */
185 long maxfd = mp_open_max();
205 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)
206 return -1; 187 return -1;
207 188
@@ -293,7 +274,6 @@ _cmd_fetch_output (int fd, output * op, int flags)
293int 274int
294cmd_run (const char *cmdstring, output * out, output * err, int flags) 275cmd_run (const char *cmdstring, output * out, output * err, int flags)
295{ 276{
296 int fd, pfd_out[2], pfd_err[2];
297 int i = 0, argc; 277 int i = 0, argc;
298 size_t cmdlen; 278 size_t cmdlen;
299 char **argv = NULL; 279 char **argv = NULL;
@@ -406,3 +386,20 @@ cmd_file_read ( char *filename, output *out, int flags)
406 386
407 return 0; 387 return 0;
408} 388}
389
390void
391timeout_alarm_handler (int signo)
392{
393 size_t i;
394 if (signo == SIGALRM) {
395 printf (_("%s - Plugin timed out after %d seconds\n"),
396 state_text(timeout_state), timeout_interval);
397
398 long maxfd = mp_open_max();
399 if(_cmd_pids) for(i = 0; i < maxfd; i++) {
400 if(_cmd_pids[i] != 0) kill(_cmd_pids[i], SIGKILL);
401 }
402
403 exit (timeout_state);
404 }
405}