diff options
author | Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> | 2025-09-15 14:06:55 +0200 |
---|---|---|
committer | Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> | 2025-09-15 14:06:55 +0200 |
commit | f855c5b5bbbc6d5436741fd8108be64825a3c76b (patch) | |
tree | 0ee1242bc21dc75a12fae03a5bb211fe10c89625 /lib/utils_cmd.c | |
parent | 8ef825d85fb4d09c32ca44c545d6eb8d995ddea4 (diff) | |
download | monitoring-plugins-f855c5b5bbbc6d5436741fd8108be64825a3c76b.tar.gz |
general refactorin in lib, more local variables, real booleans
Diffstat (limited to 'lib/utils_cmd.c')
-rw-r--r-- | lib/utils_cmd.c | 107 |
1 files changed, 49 insertions, 58 deletions
diff --git a/lib/utils_cmd.c b/lib/utils_cmd.c index d1feaa33..35b83297 100644 --- a/lib/utils_cmd.c +++ b/lib/utils_cmd.c | |||
@@ -40,7 +40,6 @@ | |||
40 | 40 | ||
41 | /** includes **/ | 41 | /** includes **/ |
42 | #include "common.h" | 42 | #include "common.h" |
43 | #include "utils.h" | ||
44 | #include "utils_cmd.h" | 43 | #include "utils_cmd.h" |
45 | /* This variable must be global, since there's no way the caller | 44 | /* This variable must be global, since there's no way the caller |
46 | * can forcibly slay a dead or ungainly running program otherwise. | 45 | * can forcibly slay a dead or ungainly running program otherwise. |
@@ -62,9 +61,6 @@ static pid_t *_cmd_pids = NULL; | |||
62 | # include <sys/wait.h> | 61 | # include <sys/wait.h> |
63 | #endif | 62 | #endif |
64 | 63 | ||
65 | /* used in _cmd_open to pass the environment to commands */ | ||
66 | extern char **environ; | ||
67 | |||
68 | /** macros **/ | 64 | /** macros **/ |
69 | #ifndef WEXITSTATUS | 65 | #ifndef WEXITSTATUS |
70 | # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) | 66 | # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) |
@@ -80,14 +76,12 @@ extern char **environ; | |||
80 | #endif | 76 | #endif |
81 | 77 | ||
82 | /** prototypes **/ | 78 | /** prototypes **/ |
83 | static int _cmd_open(char *const *, int *, int *) __attribute__((__nonnull__(1, 2, 3))); | 79 | static int _cmd_open(char *const *argv, int *pfd, int *pfderr) |
84 | 80 | __attribute__((__nonnull__(1, 2, 3))); | |
85 | static int _cmd_fetch_output(int, output *, int) __attribute__((__nonnull__(2))); | ||
86 | 81 | ||
87 | static int _cmd_close(int); | 82 | static int _cmd_fetch_output(int fileDescriptor, output *cmd_output, int flags) __attribute__((__nonnull__(2))); |
88 | 83 | ||
89 | /* prototype imported from utils.h */ | 84 | static int _cmd_close(int fileDescriptor); |
90 | extern void die(int, const char *, ...) __attribute__((__noreturn__, __format__(__printf__, 2, 3))); | ||
91 | 85 | ||
92 | /* this function is NOT async-safe. It is exported so multithreaded | 86 | /* this function is NOT async-safe. It is exported so multithreaded |
93 | * plugins (or other apps) can call it prior to running any commands | 87 | * plugins (or other apps) can call it prior to running any commands |
@@ -110,7 +104,6 @@ void cmd_init(void) { | |||
110 | 104 | ||
111 | /* Start running a command, array style */ | 105 | /* Start running a command, array style */ |
112 | static int _cmd_open(char *const *argv, int *pfd, int *pfderr) { | 106 | static int _cmd_open(char *const *argv, int *pfd, int *pfderr) { |
113 | pid_t pid; | ||
114 | #ifdef RLIMIT_CORE | 107 | #ifdef RLIMIT_CORE |
115 | struct rlimit limit; | 108 | struct rlimit limit; |
116 | #endif | 109 | #endif |
@@ -123,6 +116,7 @@ static int _cmd_open(char *const *argv, int *pfd, int *pfderr) { | |||
123 | 116 | ||
124 | setenv("LC_ALL", "C", 1); | 117 | setenv("LC_ALL", "C", 1); |
125 | 118 | ||
119 | pid_t pid; | ||
126 | if (pipe(pfd) < 0 || pipe(pfderr) < 0 || (pid = fork()) < 0) { | 120 | if (pipe(pfd) < 0 || pipe(pfderr) < 0 || (pid = fork()) < 0) { |
127 | return -1; /* errno set by the failing function */ | 121 | return -1; /* errno set by the failing function */ |
128 | } | 122 | } |
@@ -171,22 +165,23 @@ static int _cmd_open(char *const *argv, int *pfd, int *pfderr) { | |||
171 | return pfd[0]; | 165 | return pfd[0]; |
172 | } | 166 | } |
173 | 167 | ||
174 | static int _cmd_close(int fd) { | 168 | static int _cmd_close(int fileDescriptor) { |
175 | int status; | ||
176 | pid_t pid; | 169 | pid_t pid; |
177 | 170 | ||
178 | /* make sure the provided fd was opened */ | 171 | /* make sure the provided fd was opened */ |
179 | long maxfd = mp_open_max(); | 172 | long maxfd = mp_open_max(); |
180 | if (fd < 0 || fd > maxfd || !_cmd_pids || (pid = _cmd_pids[fd]) == 0) { | 173 | if (fileDescriptor < 0 || fileDescriptor > maxfd || !_cmd_pids || |
174 | (pid = _cmd_pids[fileDescriptor]) == 0) { | ||
181 | return -1; | 175 | return -1; |
182 | } | 176 | } |
183 | 177 | ||
184 | _cmd_pids[fd] = 0; | 178 | _cmd_pids[fileDescriptor] = 0; |
185 | if (close(fd) == -1) { | 179 | if (close(fileDescriptor) == -1) { |
186 | return -1; | 180 | return -1; |
187 | } | 181 | } |
188 | 182 | ||
189 | /* EINTR is ok (sort of), everything else is bad */ | 183 | /* EINTR is ok (sort of), everything else is bad */ |
184 | int status; | ||
190 | while (waitpid(pid, &status, 0) < 0) { | 185 | while (waitpid(pid, &status, 0) < 0) { |
191 | if (errno != EINTR) { | 186 | if (errno != EINTR) { |
192 | return -1; | 187 | return -1; |
@@ -197,68 +192,67 @@ static int _cmd_close(int fd) { | |||
197 | return (WIFEXITED(status)) ? WEXITSTATUS(status) : -1; | 192 | return (WIFEXITED(status)) ? WEXITSTATUS(status) : -1; |
198 | } | 193 | } |
199 | 194 | ||
200 | static int _cmd_fetch_output(int fd, output *op, int flags) { | 195 | static int _cmd_fetch_output(int fileDescriptor, output *cmd_output, int flags) { |
201 | size_t len = 0, i = 0, lineno = 0; | ||
202 | size_t rsf = 6, ary_size = 0; /* rsf = right shift factor, dec'ed uncond once */ | ||
203 | char *buf = NULL; | ||
204 | int ret; | ||
205 | char tmpbuf[4096]; | 196 | char tmpbuf[4096]; |
206 | 197 | cmd_output->buf = NULL; | |
207 | op->buf = NULL; | 198 | cmd_output->buflen = 0; |
208 | op->buflen = 0; | 199 | ssize_t ret; |
209 | while ((ret = read(fd, tmpbuf, sizeof(tmpbuf))) > 0) { | 200 | while ((ret = read(fileDescriptor, tmpbuf, sizeof(tmpbuf))) > 0) { |
210 | len = (size_t)ret; | 201 | size_t len = (size_t)ret; |
211 | op->buf = realloc(op->buf, op->buflen + len + 1); | 202 | cmd_output->buf = realloc(cmd_output->buf, cmd_output->buflen + len + 1); |
212 | memcpy(op->buf + op->buflen, tmpbuf, len); | 203 | memcpy(cmd_output->buf + cmd_output->buflen, tmpbuf, len); |
213 | op->buflen += len; | 204 | cmd_output->buflen += len; |
214 | i++; | ||
215 | } | 205 | } |
216 | 206 | ||
217 | if (ret < 0) { | 207 | if (ret < 0) { |
218 | printf("read() returned %d: %s\n", ret, strerror(errno)); | 208 | printf("read() returned %zd: %s\n", ret, strerror(errno)); |
219 | return ret; | 209 | return ret; |
220 | } | 210 | } |
221 | 211 | ||
222 | /* some plugins may want to keep output unbroken, and some commands | 212 | /* some plugins may want to keep output unbroken, and some commands |
223 | * will yield no output, so return here for those */ | 213 | * will yield no output, so return here for those */ |
224 | if (flags & CMD_NO_ARRAYS || !op->buf || !op->buflen) { | 214 | if (flags & CMD_NO_ARRAYS || !cmd_output->buf || !cmd_output->buflen) { |
225 | return op->buflen; | 215 | return cmd_output->buflen; |
226 | } | 216 | } |
227 | 217 | ||
228 | /* and some may want both */ | 218 | /* and some may want both */ |
219 | char *buf = NULL; | ||
229 | if (flags & CMD_NO_ASSOC) { | 220 | if (flags & CMD_NO_ASSOC) { |
230 | buf = malloc(op->buflen); | 221 | buf = malloc(cmd_output->buflen); |
231 | memcpy(buf, op->buf, op->buflen); | 222 | memcpy(buf, cmd_output->buf, cmd_output->buflen); |
232 | } else { | 223 | } else { |
233 | buf = op->buf; | 224 | buf = cmd_output->buf; |
234 | } | 225 | } |
235 | 226 | ||
236 | op->line = NULL; | 227 | cmd_output->line = NULL; |
237 | op->lens = NULL; | 228 | cmd_output->lens = NULL; |
238 | i = 0; | 229 | size_t i = 0; |
239 | while (i < op->buflen) { | 230 | size_t ary_size = 0; /* rsf = right shift factor, dec'ed uncond once */ |
231 | size_t rsf = 6; | ||
232 | size_t lineno = 0; | ||
233 | while (i < cmd_output->buflen) { | ||
240 | /* make sure we have enough memory */ | 234 | /* make sure we have enough memory */ |
241 | if (lineno >= ary_size) { | 235 | if (lineno >= ary_size) { |
242 | /* ary_size must never be zero */ | 236 | /* ary_size must never be zero */ |
243 | do { | 237 | do { |
244 | ary_size = op->buflen >> --rsf; | 238 | ary_size = cmd_output->buflen >> --rsf; |
245 | } while (!ary_size); | 239 | } while (!ary_size); |
246 | 240 | ||
247 | op->line = realloc(op->line, ary_size * sizeof(char *)); | 241 | cmd_output->line = realloc(cmd_output->line, ary_size * sizeof(char *)); |
248 | op->lens = realloc(op->lens, ary_size * sizeof(size_t)); | 242 | cmd_output->lens = realloc(cmd_output->lens, ary_size * sizeof(size_t)); |
249 | } | 243 | } |
250 | 244 | ||
251 | /* set the pointer to the string */ | 245 | /* set the pointer to the string */ |
252 | op->line[lineno] = &buf[i]; | 246 | cmd_output->line[lineno] = &buf[i]; |
253 | 247 | ||
254 | /* hop to next newline or end of buffer */ | 248 | /* hop to next newline or end of buffer */ |
255 | while (buf[i] != '\n' && i < op->buflen) { | 249 | while (buf[i] != '\n' && i < cmd_output->buflen) { |
256 | i++; | 250 | i++; |
257 | } | 251 | } |
258 | buf[i] = '\0'; | 252 | buf[i] = '\0'; |
259 | 253 | ||
260 | /* calculate the string length using pointer difference */ | 254 | /* calculate the string length using pointer difference */ |
261 | op->lens[lineno] = (size_t)&buf[i] - (size_t)op->line[lineno]; | 255 | cmd_output->lens[lineno] = (size_t)&buf[i] - (size_t)cmd_output->line[lineno]; |
262 | 256 | ||
263 | lineno++; | 257 | lineno++; |
264 | i++; | 258 | i++; |
@@ -268,12 +262,6 @@ static int _cmd_fetch_output(int fd, output *op, int flags) { | |||
268 | } | 262 | } |
269 | 263 | ||
270 | int cmd_run(const char *cmdstring, output *out, output *err, int flags) { | 264 | int cmd_run(const char *cmdstring, output *out, output *err, int flags) { |
271 | int i = 0, argc; | ||
272 | size_t cmdlen; | ||
273 | char **argv = NULL; | ||
274 | char *cmd = NULL; | ||
275 | char *str = NULL; | ||
276 | |||
277 | if (cmdstring == NULL) { | 265 | if (cmdstring == NULL) { |
278 | return -1; | 266 | return -1; |
279 | } | 267 | } |
@@ -288,7 +276,8 @@ int cmd_run(const char *cmdstring, output *out, output *err, int flags) { | |||
288 | 276 | ||
289 | /* make copy of command string so strtok() doesn't silently modify it */ | 277 | /* make copy of command string so strtok() doesn't silently modify it */ |
290 | /* (the calling program may want to access it later) */ | 278 | /* (the calling program may want to access it later) */ |
291 | cmdlen = strlen(cmdstring); | 279 | size_t cmdlen = strlen(cmdstring); |
280 | char *cmd = NULL; | ||
292 | if ((cmd = malloc(cmdlen + 1)) == NULL) { | 281 | if ((cmd = malloc(cmdlen + 1)) == NULL) { |
293 | return -1; | 282 | return -1; |
294 | } | 283 | } |
@@ -307,8 +296,8 @@ int cmd_run(const char *cmdstring, output *out, output *err, int flags) { | |||
307 | 296 | ||
308 | /* each arg must be whitespace-separated, so args can be a maximum | 297 | /* each arg must be whitespace-separated, so args can be a maximum |
309 | * of (len / 2) + 1. We add 1 extra to the mix for NULL termination */ | 298 | * of (len / 2) + 1. We add 1 extra to the mix for NULL termination */ |
310 | argc = (cmdlen >> 1) + 2; | 299 | int argc = (cmdlen >> 1) + 2; |
311 | argv = calloc((size_t)argc, sizeof(char *)); | 300 | char **argv = calloc((size_t)argc, sizeof(char *)); |
312 | 301 | ||
313 | if (argv == NULL) { | 302 | if (argv == NULL) { |
314 | printf("%s\n", _("Could not malloc argv array in popen()")); | 303 | printf("%s\n", _("Could not malloc argv array in popen()")); |
@@ -316,8 +305,9 @@ int cmd_run(const char *cmdstring, output *out, output *err, int flags) { | |||
316 | } | 305 | } |
317 | 306 | ||
318 | /* get command arguments (stupidly, but fairly quickly) */ | 307 | /* get command arguments (stupidly, but fairly quickly) */ |
308 | int i = 0; | ||
319 | while (cmd) { | 309 | while (cmd) { |
320 | str = cmd; | 310 | char *str = cmd; |
321 | str += strspn(str, " \t\r\n"); /* trim any leading whitespace */ | 311 | str += strspn(str, " \t\r\n"); /* trim any leading whitespace */ |
322 | 312 | ||
323 | if (strstr(str, "'") == str) { /* handle SIMPLE quoted strings */ | 313 | if (strstr(str, "'") == str) { /* handle SIMPLE quoted strings */ |
@@ -347,8 +337,6 @@ int cmd_run(const char *cmdstring, output *out, output *err, int flags) { | |||
347 | } | 337 | } |
348 | 338 | ||
349 | int cmd_run_array(char *const *argv, output *out, output *err, int flags) { | 339 | int cmd_run_array(char *const *argv, output *out, output *err, int flags) { |
350 | int fd, pfd_out[2], pfd_err[2]; | ||
351 | |||
352 | /* initialize the structs */ | 340 | /* initialize the structs */ |
353 | if (out) { | 341 | if (out) { |
354 | memset(out, 0, sizeof(output)); | 342 | memset(out, 0, sizeof(output)); |
@@ -357,6 +345,9 @@ int cmd_run_array(char *const *argv, output *out, output *err, int flags) { | |||
357 | memset(err, 0, sizeof(output)); | 345 | memset(err, 0, sizeof(output)); |
358 | } | 346 | } |
359 | 347 | ||
348 | int fd; | ||
349 | int pfd_out[2]; | ||
350 | int pfd_err[2]; | ||
360 | if ((fd = _cmd_open(argv, pfd_out, pfd_err)) == -1) { | 351 | if ((fd = _cmd_open(argv, pfd_out, pfd_err)) == -1) { |
361 | die(STATE_UNKNOWN, _("Could not open pipe: %s\n"), argv[0]); | 352 | die(STATE_UNKNOWN, _("Could not open pipe: %s\n"), argv[0]); |
362 | } | 353 | } |