diff -urN ../nplg/plugins/check_by_ssh.c ./plugins/check_by_ssh.c --- ../nplg/plugins/check_by_ssh.c 2005-01-05 21:53:11.000000000 +0100 +++ ./plugins/check_by_ssh.c 2005-06-10 15:01:26.000000000 +0200 @@ -14,19 +14,19 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: check_by_ssh.c,v 1.35 2004/12/25 12:09:19 opensides Exp $ + $Id: check_by_ssh.c,v 1.3 2005/06/06 11:37:06 exon Exp $ *****************************************************************************/ const char *progname = "check_by_ssh"; -const char *revision = "$Revision: 1.35 $"; +const char *revision = "$Revision: 1.3 $"; const char *copyright = "2000-2004"; const char *email = "nagiosplug-devel@lists.sourceforge.net"; #include "common.h" #include "netutils.h" #include "utils.h" -#include "popen.h" +#include "runcmd.h" int process_arguments (int, char **); int validate_arguments (void); @@ -49,15 +49,15 @@ main (int argc, char **argv) { - char input_buffer[MAX_INPUT_BUFFER]; char *result_text; char *status_text; - char *output; + char *msg; char *eol = NULL; int cresult; int result = STATE_UNKNOWN; time_t local_time; FILE *fp = NULL; + struct output chld_out, chld_err; remotecmd = strdup (""); comm = strdup (SSH_COMMAND); @@ -82,48 +82,22 @@ if (verbose) printf ("%s\n", comm); - child_process = spopen (comm); - - if (child_process == NULL) { - printf (_("Could not open pipe: %s\n"), comm); - return STATE_UNKNOWN; - } - - - /* open STDERR for spopen */ - child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); - if (child_stderr == NULL) { - printf (_("Could not open stderr for %s\n"), SSH_COMMAND); - } - + result = np_runcmd(comm, &chld_out, &chld_err, 0); /* build up results from remote command in result_text */ - while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) - asprintf (&result_text, "%s%s", result_text, input_buffer); + if(skip_lines && skip_lines < chld_out.lines) + result_text = chld_out.line[skip_lines]; + else + result_text = chld_out.line[0]; /* WARNING if output found on stderr */ - while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { - if (skip_lines > 0) { - if (input_buffer[strlen(input_buffer)-1] == '\n') { - skip_lines--; - } - } else { - printf ("%s", input_buffer); - result = STATE_WARNING; - } + if(chld_err.buflen) { + printf("%s\n", chld_err.line[0]); + return STATE_WARNING; } - (void) fclose (child_stderr); - if (result == STATE_WARNING) - return result; - - - /* close the pipe */ - result = spclose (child_process); - /* process output */ if (passive) { - if (!(fp = fopen (outputfile, "a"))) { printf (_("SSH WARNING: could not open %s\n"), outputfile); exit (STATE_UNKNOWN); @@ -137,19 +111,19 @@ printf ("%s", result_text); return result; } - asprintf (&output, "%s", result_text); + asprintf (&msg, "%s", result_text); result_text = strnl (status_text); - eol = strpbrk (output, "\r\n"); + eol = strpbrk (msg, "\r\n"); if (eol != NULL) eol[0] = 0; if (service[commands] && status_text - && sscanf (status_text, "STATUS CODE: %d", &cresult) == 1) { + && sscanf (status_text, "STATUS CODE: %d", &cresult) == 1) + { fprintf (fp, "[%d] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n", - (int) local_time, host_shortname, service[commands++], cresult, - output); + (int) local_time, host_shortname, service[commands++], + cresult, msg); } } - } @@ -206,7 +180,7 @@ while (1) { c = getopt_long (argc, argv, "Vvh1246ft:H:O:p:i:u:l:C:S:n:s:", longopts, - &option); + &option); if (c == -1 || c == EOF) break; @@ -244,25 +218,27 @@ passive = TRUE; break; case 's': /* description of service to check */ - service = realloc (service, (++services) * sizeof(char *)); p1 = optarg; + service = realloc (service, (++services) * sizeof(char *)); while ((p2 = index (p1, ':'))) { *p2 = '\0'; - asprintf (&service[services-1], "%s", p1); + service[services - 1] = p1; service = realloc (service, (++services) * sizeof(char *)); p1 = p2 + 1; } - asprintf (&service[services-1], "%s", p1); + service[services - 1] = p1; break; case 'n': /* short name of host in nagios configuration */ host_shortname = optarg; break; + case 'u': c = 'l'; case 'l': /* login name */ case 'i': /* identity */ asprintf (&comm, "%s -%c %s", comm, c, optarg); break; + case '1': /* Pass these switches directly to ssh */ case '2': /* 1 to force version 1, 2 to force version 2 */ case '4': /* -4 for IPv4 */ diff -urN ../nplg/plugins/check_dig.c ./plugins/check_dig.c --- ../nplg/plugins/check_dig.c 2005-01-28 15:00:58.000000000 +0100 +++ ./plugins/check_dig.c 2005-06-10 15:01:26.000000000 +0200 @@ -14,29 +14,33 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: check_dig.c,v 1.40 2005/01/26 21:21:01 tonvoon Exp $ + $Id: check_dig.c,v 1.3 2005/06/06 11:37:06 exon Exp $ *****************************************************************************/ +/* Hackers note: + * There are typecasts to (char *) from _("foo bar") in this file. + * They prevent compiler warnings. Never (ever), permute strings obtained + * that are typecast from (const char *) (which happens when --disable-nls) + * because on some architectures those strings are in non-writable memory */ + const char *progname = "check_dig"; -const char *revision = "$Revision: 1.40 $"; +const char *revision = "$Revision: 1.3 $"; const char *copyright = "2002-2004"; const char *email = "nagiosplug-devel@lists.sourceforge.net"; #include "common.h" #include "netutils.h" #include "utils.h" -#include "popen.h" +#include "runcmd.h" int process_arguments (int, char **); int validate_arguments (void); void print_help (void); void print_usage (void); -enum { - UNDEFINED = 0, - DEFAULT_PORT = 53 -}; +#define UNDEFINED 0 +#define DEFAULT_PORT 53 char *query_address = NULL; char *record_type = "A"; @@ -51,16 +55,15 @@ int main (int argc, char **argv) { - char input_buffer[MAX_INPUT_BUFFER]; char *command_line; - char *output; + output chld_out, chld_err; + char *msg = NULL; + size_t i; char *t; long microsec; double elapsed_time; int result = STATE_UNKNOWN; - output = strdup (""); - setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); @@ -89,100 +92,75 @@ } /* run the command */ - child_process = spopen (command_line); - if (child_process == NULL) { - printf (_("Could not open pipe: %s\n"), command_line); - return STATE_UNKNOWN; + if((result = np_runcmd(command_line, &chld_out, &chld_err, 0)) != 0) { + result = STATE_WARNING; + msg = (char *)_("dig returned an error status"); } - child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); - if (child_stderr == NULL) - printf (_("Could not open stderr for %s\n"), command_line); - - while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { - + for(i = 0; i < chld_out.lines; i++) { /* the server is responding, we just got the host name... */ - if (strstr (input_buffer, ";; ANSWER SECTION:")) { + if (strstr (chld_out.line[i], ";; ANSWER SECTION:")) { /* loop through the whole 'ANSWER SECTION' */ - do { + for(; i < chld_out.lines; i++) { /* get the host address */ - if (!fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) - break; - - if (strpbrk (input_buffer, "\r\n")) - input_buffer[strcspn (input_buffer, "\r\n")] = '\0'; + if (verbose) + printf ("%s\n", chld_out.line[i]); - if (verbose && !strstr (input_buffer, ";; ")) - printf ("%s\n", input_buffer); - - if (expected_address==NULL && strstr (input_buffer, query_address) != NULL) { - output = strdup(input_buffer); + if (strstr (chld_out.line[i], (expected_address == NULL ? query_address : expected_address)) != NULL) { + msg = chld_out.line[i]; result = STATE_OK; - } - else if (expected_address != NULL && strstr (input_buffer, expected_address) != NULL) { - output = strdup(input_buffer); - result = STATE_OK; - } - /* Translate output TAB -> SPACE */ - t = output; - while ((t = index(t, '\t')) != NULL) - *t = ' '; - - } while (!strstr (input_buffer, ";; ")); + /* Translate output TAB -> SPACE */ + t = msg; + while ((t = strchr(t, '\t')) != NULL) *t = ' '; + break; + } + } if (result == STATE_UNKNOWN) { - asprintf (&output, _("Server not found in ANSWER SECTION")); - result = STATE_WARNING; - } - } - - } - - if (result == STATE_UNKNOWN) { - asprintf (&output, _("No ANSWER SECTION found")); - } + msg = (char *)_("Server not found in ANSWER SECTION"); + result = STATE_WARNING; + } - while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { - /* If we get anything on STDERR, at least set warning */ - result = max_state (result, STATE_WARNING); - printf ("%s", input_buffer); - if (strlen (output) == 0) - output = strdup (1 + index (input_buffer, ':')); + /* we found the answer section, so break out of the loop */ + break; + } } - (void) fclose (child_stderr); + if (result == STATE_UNKNOWN) + msg = (char *)_("No ANSWER SECTION found"); - /* close the pipe */ - if (spclose (child_process)) { - result = max_state (result, STATE_WARNING); - if (strlen (output) == 0) - asprintf (&output, _("dig returned an error status")); + /* If we get anything on STDERR, at least set warning */ + if(chld_err.buflen > 0) { + result = max_state(result, STATE_WARNING); + if(!msg) for(i = 0; i < chld_err.lines; i++) { + msg = strchr(chld_err.line[0], ':'); + if(msg) { + msg++; + break; + } + } } microsec = deltime (tv); elapsed_time = (double)microsec / 1.0e6; - if (output == NULL || strlen (output) == 0) - asprintf (&output, _(" Probably a non-existent host/domain")); - if (critical_interval > UNDEFINED && elapsed_time > critical_interval) result = STATE_CRITICAL; else if (warning_interval > UNDEFINED && elapsed_time > warning_interval) result = STATE_WARNING; - asprintf (&output, _("%.3f seconds response time (%s)"), elapsed_time, output); - - printf ("DNS %s - %s|%s\n", - state_text (result), output, + printf ("DNS %s - %.3f seconds response time (%s)|%s\n", + state_text (result), elapsed_time, + msg ? msg : _("Probably a non-existent host/domain"), fperfdata("time", elapsed_time, "s", - (warning_interval>UNDEFINED?TRUE:FALSE), - warning_interval, - (critical_interval>UNDEFINED?TRUE:FALSE), - critical_interval, - TRUE, 0, FALSE, 0)); + (warning_interval>UNDEFINED?TRUE:FALSE), + warning_interval, + (critical_interval>UNDEFINED?TRUE:FALSE), + critical_interval, + TRUE, 0, FALSE, 0)); return result; } @@ -359,6 +337,6 @@ { printf ("\ Usage: %s -H host -l lookup [-p ] [-T ]\n\ - [-w ] [-c ] [-t ]\n\ - [-a ] [-v]\n", progname); + [-w ] [-c ] [-t ]\n\ + [-a ] [-v]\n", progname); } diff -urN ../nplg/plugins/check_dns.c ./plugins/check_dns.c --- ../nplg/plugins/check_dns.c 2005-01-05 21:53:12.000000000 +0100 +++ ./plugins/check_dns.c 2005-06-10 15:01:26.000000000 +0200 @@ -17,19 +17,19 @@ LIMITATION: nslookup on Solaris 7 can return output over 2 lines, which will not be picked up by this plugin - $Id: check_dns.c,v 1.47 2004/12/30 00:41:39 opensides Exp $ + $Id: check_dns.c,v 1.3 2005/06/06 11:37:06 exon Exp $ ******************************************************************************/ const char *progname = "check_dns"; -const char *revision = "$Revision: 1.47 $"; +const char *revision = "$Revision: 1.3 $"; const char *copyright = "2000-2004"; const char *email = "nagiosplug-devel@lists.sourceforge.net"; #include "common.h" -#include "popen.h" #include "utils.h" #include "netutils.h" +#include "runcmd.h" int process_arguments (int, char **); int validate_arguments (void); @@ -51,8 +51,8 @@ { char *command_line = NULL; char input_buffer[MAX_INPUT_BUFFER]; - char *output = NULL; char *address = NULL; + char *msg = NULL; char *temp_buffer = NULL; int non_authoritative = FALSE; int result = STATE_UNKNOWN; @@ -61,6 +61,8 @@ struct timeval tv; int multi_address; int parse_address = FALSE; /* This flag scans for Address: but only after Name: */ + output chld_out, chld_err; + size_t i; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); @@ -85,37 +87,31 @@ printf ("%s\n", command_line); /* run the command */ - child_process = spopen (command_line); - if (child_process == NULL) { - printf (_("Could not open pipe: %s\n"), command_line); - return STATE_UNKNOWN; + if((np_runcmd(command_line, &chld_out, &chld_err, 0)) != 0) { + msg = (char *)_("nslookup returned error status"); + result = STATE_WARNING; } - child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); - if (child_stderr == NULL) - printf (_("Could not open stderr for %s\n"), command_line); - /* scan stdout */ - while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { - + for(i = 0; i < chld_out.lines; i++) { if (verbose) - printf ("%s", input_buffer); + printf ("%s", chld_out.line[i]); - if (strstr (input_buffer, ".in-addr.arpa")) { - if ((temp_buffer = strstr (input_buffer, "name = "))) + if (strstr (chld_out.line[i], ".in-addr.arpa")) { + if ((temp_buffer = strstr (chld_out.line[i], "name = "))) address = strdup (temp_buffer + 7); else { - output = strdup (_("Warning plugin error")); + msg = (char *)_("Warning plugin error"); result = STATE_WARNING; } } /* the server is responding, we just got the host name... */ - if (strstr (input_buffer, "Name:")) + if (strstr (chld_out.line[i], "Name:")) parse_address = TRUE; - else if (parse_address == TRUE && (strstr (input_buffer, "Address:") || - strstr (input_buffer, "Addresses:"))) { - temp_buffer = index (input_buffer, ':'); + else if (parse_address == TRUE && (strstr (chld_out.line[i], "Address:") || + strstr (chld_out.line[i], "Addresses:"))) { + temp_buffer = index (chld_out.line[i], ':'); temp_buffer++; /* Strip leading spaces */ @@ -135,59 +131,47 @@ asprintf(&address, "%s,%s", address, temp_buffer); } - else if (strstr (input_buffer, _("Non-authoritative answer:"))) { + else if (strstr (chld_out.line[i], _("Non-authoritative answer:"))) { non_authoritative = TRUE; } - result = error_scan (input_buffer); + result = error_scan (chld_out.line[i]); if (result != STATE_OK) { - output = strdup (1 + index (input_buffer, ':')); - strip (output); + msg = strchr (chld_out.line[i], ':'); + if(msg) msg++; break; } - } /* scan stderr */ - while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { - + for(i = 0; i < chld_err.lines; i++) { if (verbose) - printf ("%s", input_buffer); + printf ("%s", chld_err.line[i]); - if (error_scan (input_buffer) != STATE_OK) { - result = max_state (result, error_scan (input_buffer)); - output = strdup (1 + index (input_buffer, ':')); - strip (output); + if (error_scan (chld_err.line[i]) != STATE_OK) { + result = max_state (result, error_scan (chld_err.line[i])); + msg = strchr(input_buffer, ':'); + if(msg) msg++; } } - /* close stderr */ - (void) fclose (child_stderr); - - /* close stdout */ - if (spclose (child_process)) { - result = max_state (result, STATE_WARNING); - if (output == NULL || !strcmp (output, "")) - output = strdup (_("nslookup returned error status")); - } - - /* If we got here, we should have an address string, - and we can segfault if we do not */ + /* If we got here, we should have an address string, + * and we can segfault if we do not */ if (address==NULL || strlen(address)==0) die (STATE_CRITICAL, - _("DNS CRITICAL - '%s' output parsing exited with no address\n"), + _("DNS CRITICAL - '%s' msg parsing exited with no address\n"), NSLOOKUP_COMMAND); /* compare to expected address */ if (result == STATE_OK && match_expected_address && strcmp(address, expected_address)) { result = STATE_CRITICAL; - asprintf(&output, _("expected %s but got %s"), expected_address, address); + asprintf(&msg, _("expected %s but got %s"), expected_address, address); } /* check if authoritative */ if (result == STATE_OK && expect_authority && non_authoritative) { result = STATE_CRITICAL; - asprintf(&output, _("server %s is not authoritative for %s"), dns_server, query_address); + asprintf(&msg, _("server %s is not authoritative for %s"), dns_server, query_address); } microsec = deltime (tv); @@ -206,13 +190,13 @@ } else if (result == STATE_WARNING) printf (_("DNS WARNING - %s\n"), - !strcmp (output, "") ? _(" Probably a non-existent host/domain") : output); + !strcmp (msg, "") ? _(" Probably a non-existent host/domain") : msg); else if (result == STATE_CRITICAL) printf (_("DNS CRITICAL - %s\n"), - !strcmp (output, "") ? _(" Probably a non-existent host/domain") : output); + !strcmp (msg, "") ? _(" Probably a non-existent host/domain") : msg); else printf (_("DNS UNKNOW - %s\n"), - !strcmp (output, "") ? _(" Probably a non-existent host/domain") : output); + !strcmp (msg, "") ? _(" Probably a non-existent host/domain") : msg); return result; } diff -urN ../nplg/plugins/check_fping.c ./plugins/check_fping.c --- ../nplg/plugins/check_fping.c 2005-01-05 21:53:13.000000000 +0100 +++ ./plugins/check_fping.c 2005-06-10 15:01:26.000000000 +0200 @@ -14,26 +14,24 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: check_fping.c,v 1.24 2004/12/25 23:17:44 opensides Exp $ + $Id: check_fping.c,v 1.2 2005/06/05 21:55:26 exon Exp $ ******************************************************************************/ const char *progname = "check_fping"; -const char *revision = "$Revision: 1.24 $"; +const char *revision = "$Revision: 1.2 $"; const char *copyright = "2000-2004"; const char *email = "nagiosplug-devel@lists.sourceforge.net"; #include "common.h" -#include "popen.h" #include "netutils.h" #include "utils.h" +#include "runcmd.h" -enum { - PACKET_COUNT = 1, - PACKET_SIZE = 56, - PL = 0, - RTA = 1 -}; +#define PACKET_COUNT 1 +#define PACKET_SIZE 56 +#define PL 0 +#define RTA 1 int textscan (char *buf); int process_arguments (int, char **); @@ -59,11 +57,11 @@ { /* normaly should be int result = STATE_UNKNOWN; */ - int status = STATE_UNKNOWN; + int result = STATE_UNKNOWN; char *server = NULL; char *command_line = NULL; - char *input_buffer = NULL; - input_buffer = malloc (MAX_INPUT_BUFFER); + output chld_out, chld_err; + size_t i; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); @@ -79,43 +77,21 @@ packet_size, packet_count, server); if (verbose) - printf ("%s\n", command_line); + printf ("command_line: %s\n", command_line); /* run the command */ - child_process = spopen (command_line); - if (child_process == NULL) { - printf (_("Could not open pipe: %s\n"), command_line); - return STATE_UNKNOWN; - } - - child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); - if (child_stderr == NULL) { - printf (_("Could not open stderr for %s\n"), command_line); - } + if((np_runcmd(command_line, &chld_out, &chld_err, 0)) || chld_err.buflen) + result = STATE_WARNING; - while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { - if (verbose) - printf ("%s", input_buffer); - status = max_state (status, textscan (input_buffer)); - } - - /* If we get anything on STDERR, at least set warning */ - while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { - status = max_state (status, STATE_WARNING); - if (verbose) - printf ("%s", input_buffer); - status = max_state (status, textscan (input_buffer)); - } - (void) fclose (child_stderr); + for(i = 0; i < chld_out.lines; i++) + result = max_state (result, textscan (chld_out.line[i])); - /* close the pipe */ - if (spclose (child_process)) - /* need to use max_state not max */ - status = max_state (status, STATE_WARNING); + printf ("FPING %s - %s\n", state_text (result), server_name); - printf ("FPING %s - %s\n", state_text (status), server_name); + if (verbose) for(i = 0; i < chld_out.lines; i++) + printf ("%s", chld_out.line[i]); - return status; + return result; } @@ -127,7 +103,7 @@ char *losstr = NULL; double loss; double rta; - int status = STATE_UNKNOWN; + int result = STATE_UNKNOWN; if (strstr (buf, "not found")) { die (STATE_CRITICAL, _("FPING UNKNOW - %s not found\n"), server_name); @@ -143,7 +119,7 @@ } else if (strstr (buf, "is alive")) { - status = STATE_OK; + result = STATE_OK; } else if (strstr (buf, "xmt/rcv/%loss") && strstr (buf, "min/avg/max")) { @@ -156,18 +132,18 @@ loss = strtod (losstr, NULL); rta = strtod (rtastr, NULL); if (cpl_p == TRUE && loss > cpl) - status = STATE_CRITICAL; + result = STATE_CRITICAL; else if (crta_p == TRUE && rta > crta) - status = STATE_CRITICAL; + result = STATE_CRITICAL; else if (wpl_p == TRUE && loss > wpl) - status = STATE_WARNING; + result = STATE_WARNING; else if (wrta_p == TRUE && rta > wrta) - status = STATE_WARNING; + result = STATE_WARNING; else - status = STATE_OK; - die (status, + result = STATE_OK; + die (result, _("FPING %s - %s (loss=%.0f%%, rta=%f ms)|%s %s\n"), - state_text (status), server_name, loss, rta, + state_text (result), server_name, loss, rta, perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, TRUE, 0, TRUE, 100), fperfdata ("rta", rta/1.0e3, "s", wrta_p, wrta/1.0e3, crta_p, crta/1.0e3, TRUE, 0, FALSE, 0)); @@ -179,24 +155,24 @@ losstr = 1 + strstr (losstr, "/"); loss = strtod (losstr, NULL); if (atoi(losstr) == 100) - status = STATE_CRITICAL; + result = STATE_CRITICAL; else if (cpl_p == TRUE && loss > cpl) - status = STATE_CRITICAL; + result = STATE_CRITICAL; else if (wpl_p == TRUE && loss > wpl) - status = STATE_WARNING; + result = STATE_WARNING; else - status = STATE_OK; + result = STATE_OK; /* loss=%.0f%%;%d;%d;0;100 */ - die (status, _("FPING %s - %s (loss=%.0f%% )|%s\n"), - state_text (status), server_name, loss , + die (result, _("FPING %s - %s (loss=%.0f%% )|%s\n"), + state_text (result), server_name, loss , perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, TRUE, 0, TRUE, 100)); } else { - status = max_state (status, STATE_WARNING); + result = max_state (result, STATE_WARNING); } - return status; + return result; } diff -urN ../nplg/plugins/check_game.c ./plugins/check_game.c --- ../nplg/plugins/check_game.c 2005-01-05 21:53:13.000000000 +0100 +++ ./plugins/check_game.c 2005-06-10 15:01:26.000000000 +0200 @@ -14,17 +14,17 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * -* $Id: check_game.c,v 1.22 2004/12/25 23:17:44 opensides Exp $ +* $Id: check_game.c,v 1.2 2005/06/05 21:55:26 exon Exp $ *****************************************************************************/ const char *progname = "check_game"; -const char *revision = "$Revision: 1.22 $"; +const char *revision = "$Revision: 1.2 $"; const char *copyright = "2002-2004"; const char *email = "nagiosplug-devel@lists.sourceforge.net"; #include "common.h" -#include "popen.h" #include "utils.h" +#include "runcmd.h" int process_arguments (int, char **); int validate_arguments (void); @@ -57,9 +57,9 @@ char *command_line; int result = STATE_UNKNOWN; FILE *fp; - char input_buffer[MAX_INPUT_BUFFER]; char *p, *ret[QSTAT_MAX_RETURN_ARGS]; - int i; + size_t i = 0; + output chld_out; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); @@ -80,17 +80,9 @@ if (verbose > 0) printf ("%s\n", command_line); - /* run the command */ - fp = spopen (command_line); - if (fp == NULL) { - printf (_("Could not open pipe: %s\n"), command_line); - return STATE_UNKNOWN; - } - - fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp); /* Only interested in the first line */ - - /* strip the newline character from the end of the input */ - input_buffer[strlen (input_buffer) - 1] = 0; + /* run the command. historically, this plugin ignores output on stderr, + * as well as return status of the qstat program */ + (void)np_runcmd(command_line, &chld_out, NULL, 0); /* sanity check */ /* was thinking about running qstat without any options, capturing the @@ -102,18 +94,13 @@ In the end, I figured I'd simply let an error occur & then trap it */ - if (!strncmp (input_buffer, "unknown option", 14)) { + if (!strncmp (chld_out.line[0], "unknown option", 14)) { printf (_("CRITICAL - Host type parameter incorrect!\n")); result = STATE_CRITICAL; return result; } - /* initialize the returned data buffer */ - for (i = 0; i < QSTAT_MAX_RETURN_ARGS; i++) - ret[i] = strdup(""); - - i = 0; - p = (char *) strtok (input_buffer, QSTAT_DATA_DELIMITER); + p = (char *) strtok (chld_out.line[0], QSTAT_DATA_DELIMITER); while (p != NULL) { ret[i] = p; p = (char *) strtok (NULL, QSTAT_DATA_DELIMITER); @@ -141,17 +128,14 @@ ret[qstat_game_field], ret[qstat_map_field], ret[qstat_ping_field], - perfdata ("players", atol(ret[qstat_game_players]), "", + perfdata ("players", atol(ret[qstat_game_players]), "", FALSE, 0, FALSE, 0, TRUE, 0, TRUE, atol(ret[qstat_game_players_max])), - fperfdata ("ping", strtod(ret[qstat_ping_field], NULL), "", + fperfdata ("ping", strtod(ret[qstat_ping_field], NULL), "", FALSE, 0, FALSE, 0, TRUE, 0, FALSE, 0)); } - /* close the pipe */ - spclose (fp); - return result; } diff -urN ../nplg/plugins/check_hpjd.c ./plugins/check_hpjd.c --- ../nplg/plugins/check_hpjd.c 2005-01-05 21:53:13.000000000 +0100 +++ ./plugins/check_hpjd.c 2005-06-10 15:01:26.000000000 +0200 @@ -14,24 +14,22 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * -* $Id: check_hpjd.c,v 1.31 2004/12/25 23:17:44 opensides Exp $ +* $Id: check_hpjd.c,v 1.4 2005/06/06 11:37:06 exon Exp $ *****************************************************************************/ const char *progname = "check_hpjd"; -const char *revision = "$Revision: 1.31 $"; +const char *revision = "$Revision: 1.4 $"; const char *copyright = "2000-2004"; const char *email = "nagiosplug-devel@lists.sourceforge.net"; #include "common.h" -#include "popen.h" #include "utils.h" #include "netutils.h" +#include "runcmd.h" #define DEFAULT_COMMUNITY "public" - -const char *option_summary = "-H host [-C community]\n"; - +/* this macro is only avavilable from main() */ #define HPJD_LINE_STATUS ".1.3.6.1.4.1.11.2.3.9.1.1.2.1" #define HPJD_PAPER_STATUS ".1.3.6.1.4.1.11.2.3.9.1.1.2.2" #define HPJD_INTERVENTION_REQUIRED ".1.3.6.1.4.1.11.2.3.9.1.1.2.3" @@ -44,42 +42,50 @@ #define HPJD_GD_DOOR_OPEN ".1.3.6.1.4.1.11.2.3.9.1.1.2.17" #define HPJD_GD_PAPER_OUTPUT ".1.3.6.1.4.1.11.2.3.9.1.1.2.19" #define HPJD_GD_STATUS_DISPLAY ".1.3.6.1.4.1.11.2.3.9.1.1.3" +#define SNMP_VARS 12 #define ONLINE 0 #define OFFLINE 1 -int process_arguments (int, char **); -int validate_arguments (void); -void print_help (void); +/* make it compile without warnings when internationalization is disabled */ +#ifndef ENABLE_NLS +# ifdef _ +# undef _ +# endif +# define _(x) x +#endif + +static int process_arguments (int, char **); +static int validate_arguments (void); +static void print_help (void); void print_usage (void); -char *community = NULL; -char *address = NULL; +static char *community = NULL; +static char *address = NULL; + int main (int argc, char **argv) { char command_line[1024]; - int result = STATE_UNKNOWN; - int line; - char input_buffer[MAX_INPUT_BUFFER]; - char query_string[512]; - char *errmsg; - char *temp_buffer; - int line_status = ONLINE; - int paper_status = 0; - int intervention_required = 0; - int peripheral_error = 0; - int paper_jam = 0; - int paper_out = 0; - int toner_low = 0; - int page_punt = 0; - int memory_out = 0; - int door_open = 0; - int paper_output = 0; - char display_message[MAX_INPUT_BUFFER]; - - errmsg = malloc(MAX_INPUT_BUFFER); + int result = STATE_OK; + size_t i, val = 0; + int errorflag = 0; /* bitflag error tracker */ + output chld_out, chld_err; + char *errmsg_strings[11]; + + /* populate the the error message array */ + errmsg_strings[0] = _("Printer Offline"); + errmsg_strings[1] = _("Unknown Paper Error"); + errmsg_strings[2] = _("Intervention Required"); + errmsg_strings[3] = _("Peripheral Error"); + errmsg_strings[4] = _("Paper Jam"); + errmsg_strings[5] = _("Out of Paper"); + errmsg_strings[6] = _("Toner Low"); + errmsg_strings[7] = _("Data too Slow for Engine"); + errmsg_strings[8] = _("Insufficient Memory"); + errmsg_strings[9] = _("A Door is Open"); + errmsg_strings[10] = _("Output Tray is Full"); setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); @@ -88,206 +94,99 @@ if (process_arguments (argc, argv) == ERROR) usage4 (_("Could not parse arguments")); - /* removed ' 2>1' at end of command 10/27/1999 - EG */ - /* create the query string */ - sprintf - (query_string, - "%s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0", - HPJD_LINE_STATUS, - HPJD_PAPER_STATUS, - HPJD_INTERVENTION_REQUIRED, - HPJD_GD_PERIPHERAL_ERROR, - HPJD_GD_PAPER_JAM, - HPJD_GD_PAPER_OUT, - HPJD_GD_TONER_LOW, - HPJD_GD_PAGE_PUNT, - HPJD_GD_MEMORY_OUT, - HPJD_GD_DOOR_OPEN, HPJD_GD_PAPER_OUTPUT, HPJD_GD_STATUS_DISPLAY); - - /* get the command to run */ - sprintf (command_line, "%s -OQa -m : -v 1 -c %s %s %s", PATH_TO_SNMPGET, community, - address, query_string); + /* create the command-line. Get status display line first, so we can + * match line status against powersave as we parse it */ + sprintf (command_line, "%s -Oqv -m : -v 1 -c %s %s " + "%s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0", + PATH_TO_SNMPGET, community, address, + HPJD_GD_STATUS_DISPLAY, + HPJD_LINE_STATUS, + HPJD_PAPER_STATUS, + HPJD_INTERVENTION_REQUIRED, + HPJD_GD_PERIPHERAL_ERROR, + HPJD_GD_PAPER_JAM, + HPJD_GD_PAPER_OUT, + HPJD_GD_TONER_LOW, + HPJD_GD_PAGE_PUNT, + HPJD_GD_MEMORY_OUT, + HPJD_GD_DOOR_OPEN, + HPJD_GD_PAPER_OUTPUT); /* run the command */ - child_process = spopen (command_line); - if (child_process == NULL) { - printf (_("Could not open pipe: %s\n"), command_line); - return STATE_UNKNOWN; - } - - child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); - if (child_stderr == NULL) { - printf (_("Could not open stderr for %s\n"), command_line); - } - - result = STATE_OK; - - line = 0; - while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { + if((np_runcmd(command_line, &chld_out, &chld_err, 0)) || chld_err.buflen) + result = STATE_WARNING; - /* strip the newline character from the end of the input */ - if (input_buffer[strlen (input_buffer) - 1] == '\n') - input_buffer[strlen (input_buffer) - 1] = 0; - - line++; - - temp_buffer = strtok (input_buffer, "="); - temp_buffer = strtok (NULL, "="); - - if (temp_buffer == NULL) { - - result = STATE_UNKNOWN; - strcpy (errmsg, input_buffer); - - } else { - - switch (line) { - - case 1: /* 1st line should contain the line status */ - line_status = atoi (temp_buffer); - break; - case 2: /* 2nd line should contain the paper status */ - paper_status = atoi (temp_buffer); - break; - case 3: /* 3rd line should be intervention required */ - intervention_required = atoi (temp_buffer); - break; - case 4: /* 4th line should be peripheral error */ - peripheral_error = atoi (temp_buffer); - break; - case 5: /* 5th line should contain the paper jam status */ - paper_jam = atoi (temp_buffer); - break; - case 6: /* 6th line should contain the paper out status */ - paper_out = atoi (temp_buffer); - break; - case 7: /* 7th line should contain the toner low status */ - toner_low = atoi (temp_buffer); - break; - case 8: /* did data come too slow for engine */ - page_punt = atoi (temp_buffer); - break; - case 9: /* did we run out of memory */ - memory_out = atoi (temp_buffer); - break; - case 10: /* is there a door open */ - door_open = atoi (temp_buffer); - break; - case 11: /* is output tray full */ - paper_output = atoi (temp_buffer); - break; - case 12: /* display panel message */ - strcpy (display_message, temp_buffer + 1); - break; - default: - break; - } - - } - - /* break out of the read loop if we encounter an error */ - if (result != STATE_OK) - break; - } + /* if there was none or not enough output, display an error and exit */ + if (chld_out.buflen == 0 || chld_out.lines != SNMP_VARS - 1) { + if(chld_err.buflen) printf("%s : ", chld_err.line[0]); - /* WARNING if output found on stderr */ - if (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { - result = max_state (result, STATE_WARNING); - /* remove CRLF */ - if (input_buffer[strlen (input_buffer) - 1] == '\n') - input_buffer[strlen (input_buffer) - 1] = 0; - sprintf (errmsg, "%s", input_buffer ); + if(chld_out.buflen == 0) + printf (_("No data returned from %s\n"), address ); + else + printf(_("Not enough data returned from %s\n"), address); - } - - /* close stderr */ - (void) fclose (child_stderr); - - /* close the pipe */ - if (spclose (child_process)) - result = max_state (result, STATE_WARNING); - - /* if there wasn't any output, display an error */ - if (line == 0) { - - /* might not be the problem, but most likely is. */ - result = STATE_UNKNOWN ; - asprintf (&errmsg, "%s : Timeout from host %s\n", errmsg, address ); - + return STATE_UNKNOWN; } - /* if we had no read errors, check the printer status results... */ - if (result == STATE_OK) { + for(i = 1; i < chld_out.lines; i++) { + /* move to next if there's no error tag */ + if(!(val = (size_t)strtol(chld_out.line[i], NULL, 0))) + continue; + + /* tag the error */ + errorflag |= 1 << i; + + /* this switch statement is only for additional exception handling */ + switch (i) { + case 1: /* line status */ + /* clear this flag if it's powersaving (we know it's set if + * we get here, so use xor and save 2 instructions) */ + if(!strstr(chld_out.line[0], "POWERSAVE ON")) + errorflag ^= 1 << i; + break; - if (paper_jam) { - result = STATE_WARNING; - strcpy (errmsg, _("Paper Jam")); - } - else if (paper_out) { - result = STATE_WARNING; - strcpy (errmsg, _("Out of Paper")); - } - else if (line_status == OFFLINE) { - if (strcmp (errmsg, "POWERSAVE ON") != 0) { - result = STATE_WARNING; - strcpy (errmsg, _("Printer Offline")); - } - } - else if (peripheral_error) { - result = STATE_WARNING; - strcpy (errmsg, _("Peripheral Error")); - } - else if (intervention_required) { - result = STATE_WARNING; - strcpy (errmsg, _("Intervention Required")); - } - else if (toner_low) { - result = STATE_WARNING; - strcpy (errmsg, _("Toner Low")); - } - else if (memory_out) { - result = STATE_WARNING; - strcpy (errmsg, _("Insufficient Memory")); - } - else if (door_open) { - result = STATE_WARNING; - strcpy (errmsg, _("A Door is Open")); - } - else if (paper_output) { - result = STATE_WARNING; - strcpy (errmsg, _("Output Tray is Full")); - } - else if (page_punt) { - result = STATE_WARNING; - strcpy (errmsg, _("Data too Slow for Engine")); - } - else if (paper_status) { - result = STATE_WARNING; - strcpy (errmsg, _("Unknown Paper Error")); + case 2: /* paper status */ + case 3: /* intervention required */ + case 4: /* peripheral error */ + case 5: /* paper jam */ + case 6: /* paper out */ + case 7: /* toner low */ + case 8: /* data came too slow for engine */ + case 9: /* out of memory */ + case 10: /* door open */ + case 11: /* output tray full */ + break; } } - if (result == STATE_OK) - printf (_("Printer ok - (%s)\n"), display_message); - - else if (result == STATE_UNKNOWN) { + /* if some error occurred, print a starting line and all the errors */ + if(errorflag) { + printf ("%s (%s)", chld_err.buflen != 0 ? chld_err.buf : "", + chld_out.line[0]); - printf ("%s\n", errmsg); + for(i = 0; i < SNMP_VARS; i++) { /* loop the error flags */ + if((errorflag >> i) & 1) /* only print if flag is set */ + printf(" :: %s", errmsg_strings[i++]); + } - /* if printer could not be reached, escalate to critical */ - if (strstr (errmsg, "Timeout")) - result = STATE_CRITICAL; + return STATE_CRITICAL; } - else if (result == STATE_WARNING) - printf ("%s (%s)\n", errmsg, display_message); + /* set WARNING if output on stderr */ + if (chld_err.buflen) { + printf("WARNING - Printer seems ok, but %s printed to stderr (%s)", + PATH_TO_SNMPGET, chld_err.line[0]); + return STATE_WARNING; + } - return result; + /* all is well if we end up here */ + printf (_("Printer ok - (%s)\n"), chld_out.line[0]); + return STATE_OK; } /* process command-line arguments */ -int +static int process_arguments (int argc, char **argv) { int c; @@ -296,9 +195,6 @@ static struct option longopts[] = { {"hostname", required_argument, 0, 'H'}, {"community", required_argument, 0, 'C'}, -/* {"critical", required_argument,0,'c'}, */ -/* {"warning", required_argument,0,'w'}, */ -/* {"port", required_argument,0,'P'}, */ {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} @@ -307,7 +203,6 @@ if (argc < 2) return ERROR; - while (1) { c = getopt_long (argc, argv, "+hVH:C:", longopts, &option); @@ -317,7 +212,7 @@ switch (c) { case 'H': /* hostname */ if (is_host (optarg)) { - address = strscpy(address, optarg) ; + address = strdup(optarg) ; } else { usage2 (_("Invalid hostname/address"), optarg); @@ -346,26 +241,26 @@ usage2 (_("Invalid hostname/address"), argv[c]); } } - + if (community == NULL) { if (argv[c] != NULL ) community = argv[c]; else - community = strdup (DEFAULT_COMMUNITY); + community = DEFAULT_COMMUNITY; } return validate_arguments (); } -int +static int validate_arguments (void) { return OK; } -void +static void print_help (void) { print_revision (progname, revision); @@ -389,7 +284,6 @@ } - void print_usage (void) { diff -urN ../nplg/plugins/check_load.c ./plugins/check_load.c --- ../nplg/plugins/check_load.c 2005-05-30 17:44:13.000000000 +0200 +++ ./plugins/check_load.c 2005-06-10 15:01:26.000000000 +0200 @@ -14,18 +14,18 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: check_load.c,v 1.28 2005/05/28 01:21:54 seanius Exp $ + $Id: check_load.c,v 1.3 2005/06/05 21:55:26 exon Exp $ ******************************************************************************/ const char *progname = "check_load"; -const char *revision = "$Revision: 1.28 $"; +const char *revision = "$Revision: 1.3 $"; const char *copyright = "1999-2004"; const char *email = "nagiosplug-devel@lists.sourceforge.net"; #include "common.h" #include "utils.h" -#include "popen.h" +#include "runcmd.h" #ifdef HAVE_SYS_LOADAVG_H #include @@ -47,12 +47,8 @@ /* strictly for pretty-print usage in loops */ static const int nums[3] = { 1, 5, 15 }; -/* provide some fairly sane defaults */ double wload[3] = { 0.0, 0.0, 0.0 }; double cload[3] = { 0.0, 0.0, 0.0 }; -#define la1 la[0] -#define la5 la[1] -#define la15 la[2] char *status_line; @@ -86,14 +82,16 @@ main (int argc, char **argv) { int result; - int i; + size_t i; /* size_t so we can match against chld_out.lines if need be */ double la[3] = { 0.0, 0.0, 0.0 }; /* NetBSD complains about unitialized arrays */ #ifndef HAVE_GETLOADAVG - char input_buffer[MAX_INPUT_BUFFER]; # ifdef HAVE_PROC_LOADAVG + char input_buffer[MAX_INPUT_BUFFER]; FILE *fp; char *str, *next; +# else + output chld_out, chld_err; # endif #endif @@ -126,23 +124,11 @@ fclose (fp); # else - child_process = spopen (PATH_TO_UPTIME); - if (child_process == NULL) { - printf (_("Error opening %s\n"), PATH_TO_UPTIME); - return STATE_UNKNOWN; - } - child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); - if (child_stderr == NULL) { - printf (_("Could not open stderr for %s\n"), PATH_TO_UPTIME); - } - fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process); - sscanf (input_buffer, "%*[^l]load average: %f, %f, %f", &la1, &la5, &la15); + if((result = np_runcmd(PATH_TO_UPTIME, &chld_out, &chld_err, 0)) || chld_err.buflen) + die(STATE_UNKNOWN, _("Error code %d returned in %s\n"), + result, PATH_TO_UPTIME); - result = spclose (child_process); - if (result) { - printf (_("Error code %d returned in %s\n"), result, PATH_TO_UPTIME); - return STATE_UNKNOWN; - } + sscanf (chld_out.buf, "%*[^l]load average: %f, %f, %f", &la[0], &la[1], &la[2]); # endif #endif @@ -162,17 +148,17 @@ /* we got this far, so assume OK until we've measured */ result = STATE_OK; - asprintf(&status_line, _("load average: %.2f, %.2f, %.2f"), la1, la5, la15); - for(i = 0; i < 3; i++) { if(la[i] > cload[i]) { result = STATE_CRITICAL; break; } - else if(la[i] > wload[i]) result = STATE_WARNING; + + if(la[i] > wload[i]) result = STATE_WARNING; } - printf("%s - %s|", state_text(result), status_line); + printf(_("%s - load average: %.2f, %.2f, %.2f|"), + state_text(result), la[0], la[1], la[2]); for(i = 0; i < 3; i++) printf("load%d=%.3f;%.3f;%.3f;0; ", nums[i], la[i], wload[i], cload[i]); @@ -248,14 +234,13 @@ int i = 0; /* match cload first, as it will give the most friendly error message - * if user hasn't given the -c switch properly */ + * if user hasn't given the -c switch properly. Don't make sure wload[i] + * < cload[i] as it prevents users from forcing a critical state */ for(i = 0; i < 3; i++) { - if(cload[i] < 0) + if(cload[i] == 0.0) die (STATE_UNKNOWN, _("Critical threshold for %d-minute load average is not specified\n"), nums[i]); - if(wload[i] < 0) + if(wload[i] == 0.0) die (STATE_UNKNOWN, _("Warning threshold for %d-minute load average is not specified\n"), nums[i]); - if(wload[i] > cload[i]) - die (STATE_UNKNOWN, _("Parameter inconsistency: %d-minute \"warning load\" is greater than \"critical load\"\n"), nums[i]); } return OK; diff -urN ../nplg/plugins/check_nagios.c ./plugins/check_nagios.c --- ../nplg/plugins/check_nagios.c 2005-05-26 14:12:21.000000000 +0200 +++ ./plugins/check_nagios.c 2005-06-10 15:01:26.000000000 +0200 @@ -14,17 +14,17 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: check_nagios.c,v 1.26 2005/05/25 00:43:20 seanius Exp $ + $Id: check_nagios.c,v 1.3 2005/06/06 11:37:06 exon Exp $ ******************************************************************************/ const char *progname = "check_nagios"; -const char *revision = "$Revision: 1.26 $"; +const char *revision = "$Revision: 1.3 $"; const char *copyright = "1999-2004"; const char *email = "nagiosplug-devel@lists.sourceforge.net"; #include "common.h" -#include "popen.h" +#include "runcmd.h" #include "utils.h" int process_arguments (int, char **); @@ -55,6 +55,8 @@ int procrss = 0; float procpcpu = 0; char procstat[8]; + /* procetime is unused in most configurations, but may be in PS_VAR_LIST + * so it must be here in spite of it producing compiler warnings */ char procetime[MAX_INPUT_BUFFER]; char procprog[MAX_INPUT_BUFFER]; char *procargs; @@ -62,6 +64,8 @@ int expected_cols = PS_COLS - 1; const char *zombie = "Z"; char *temp_string; + output chld_out, chld_err; + size_t i; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); @@ -99,40 +103,30 @@ printf(_("command: %s\n"), PS_COMMAND); /* run the command to check for the Nagios process.. */ - child_process = spopen (PS_COMMAND); - if (child_process == NULL) { - printf (_("Could not open pipe: %s\n"), PS_COMMAND); - return STATE_UNKNOWN; - } - - child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); - if (child_stderr == NULL) { - printf (_("Could not open stderr for %s\n"), PS_COMMAND); - } - - fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process); + if((result = np_runcmd(PS_COMMAND, &chld_out, &chld_err, 0)) != 0) + result = STATE_WARNING; /* count the number of matching Nagios processes... */ - while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { - cols = sscanf (input_buffer, PS_FORMAT, PS_VARLIST); - /* Zombie processes do not give a procprog command */ - if ( cols == (expected_cols - 1) && strstr(procstat, zombie) ) { - cols = expected_cols; - /* Set some value for procargs for the strip command further below - Seen to be a problem on some Solaris 7 and 8 systems */ - input_buffer[pos] = '\n'; - input_buffer[pos+1] = 0x0; - } + for(i = 0; i < chld_out.lines; i++) { + cols = sscanf (chld_out.line[i], PS_FORMAT, PS_VARLIST); + /* Zombie processes do not give a procprog command */ + if ( cols == (expected_cols - 1) && strstr(procstat, zombie) ) { + cols = expected_cols; + /* Set some value for procargs for the strip command further below + * Seen to be a problem on some Solaris 7 and 8 systems */ + chld_out.line[i][pos] = '\n'; + chld_out.line[i][pos+1] = 0x0; + } if ( cols >= expected_cols ) { - asprintf (&procargs, "%s", input_buffer + pos); + asprintf (&procargs, "%s", chld_out.line[i] + pos); strip (procargs); - + /* Some ps return full pathname for command. This removes path */ - temp_string = strtok ((char *)procprog, "/"); - while (temp_string) { - strcpy(procprog, temp_string); - temp_string = strtok (NULL, "/"); - } + temp_string = strtok ((char *)procprog, "/"); + while (temp_string) { + strcpy(procprog, temp_string); + temp_string = strtok (NULL, "/"); + } /* May get empty procargs */ if (!strstr(procargs, argv[0]) && strstr(procargs, process_string) && strcmp(procargs,"")) { @@ -145,14 +139,7 @@ } /* If we get anything on stderr, at least set warning */ - while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) - result = max_state (result, STATE_WARNING); - - /* close stderr */ - (void) fclose (child_stderr); - - /* close the pipe */ - if (spclose (child_process)) + if(chld_err.buflen) result = max_state (result, STATE_WARNING); /* reset the alarm handler */ diff -urN ../nplg/plugins/check_ping.c ./plugins/check_ping.c --- ../nplg/plugins/check_ping.c 2005-05-26 14:12:21.000000000 +0200 +++ ./plugins/check_ping.c 2005-06-10 15:01:26.000000000 +0200 @@ -14,18 +14,18 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: check_ping.c,v 1.44 2005/05/25 14:25:55 sghosh Exp $ + $Id: check_ping.c,v 1.2 2005/06/05 21:55:26 exon Exp $ ******************************************************************************/ const char *progname = "check_ping"; -const char *revision = "$Revision: 1.44 $"; +const char *revision = "$Revision: 1.2 $"; const char *copyright = "2000-2004"; const char *email = "nagiosplug-devel@lists.sourceforge.net"; #include "common.h" #include "netutils.h" -#include "popen.h" +#include "runcmd.h" #include "utils.h" #define WARN_DUPLICATES "DUPLICATES FOUND! " @@ -40,7 +40,7 @@ int get_threshold (char *, float *, int *); int validate_arguments (void); int run_ping (const char *cmd, const char *addr); -int error_scan (char buf[MAX_INPUT_BUFFER], const char *addr); +int error_scan (const char *buf, const char *addr); void print_usage (void); void print_help (void); @@ -58,7 +58,7 @@ float rta = UNKNOWN_TRIP_TIME; int pl = UNKNOWN_PACKET_LOSS; -char *warn_text; +char *warn_text = NULL; @@ -95,10 +95,8 @@ if (is_inet6_addr(addresses[i]) && address_family != AF_INET) rawcmd = strdup(PING6_COMMAND); else - rawcmd = strdup(PING_COMMAND); -#else - rawcmd = strdup(PING_COMMAND); #endif + rawcmd = strdup(PING_COMMAND); /* does the host address of number of packets argument come first? */ #ifdef PING_PACKETS_FIRST @@ -119,8 +117,7 @@ if (pl == UNKNOWN_PACKET_LOSS || rta < 0.0) { printf ("%s\n", cmd); - die (STATE_UNKNOWN, - _("CRITICAL - Could not interpret output from ping command\n")); + die (STATE_UNKNOWN, _("CRITICAL - Could not interpret output from ping command\n")); } if (pl >= cpl || rta >= crta || rta < 0) @@ -136,11 +133,11 @@ if (display_html == TRUE) printf ("", CGIURL, addresses[i]); if (pl == 100) - printf (_("PING %s - %sPacket loss = %d%%"), state_text (this_result), warn_text, - pl); + printf (_("PING %s - %sPacket loss = %d%%"), + state_text(this_result), warn_text ? warn_text : " ", pl); else printf (_("PING %s - %sPacket loss = %d%%, RTA = %2.2f ms"), - state_text (this_result), warn_text, pl, rta); + state_text (this_result), warn_text ? warn_text : " ", pl, rta); if (display_html == TRUE) printf (""); printf ("\n"); @@ -399,42 +396,42 @@ int run_ping (const char *cmd, const char *addr) { - char buf[MAX_INPUT_BUFFER]; int result = STATE_UNKNOWN; - - if ((child_process = spopen (cmd)) == NULL) - die (STATE_UNKNOWN, _("Could not open pipe: %s\n"), cmd); - - child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); - if (child_stderr == NULL) - printf (_("Cannot open stderr for %s\n"), cmd); - - while (fgets (buf, MAX_INPUT_BUFFER - 1, child_process)) { - - result = max_state (result, error_scan (buf, addr)); - - /* get the percent loss statistics */ - if(sscanf(buf,"%*d packets transmitted, %*d packets received, +%*d errors, %d%% packet loss",&pl)==1 || - sscanf(buf,"%*d packets transmitted, %*d packets received, %d%% packet loss",&pl)==1 || - sscanf(buf,"%*d packets transmitted, %*d packets received, %d%% loss, time",&pl)==1 || - sscanf(buf,"%*d packets transmitted, %*d received, %d%% loss, time", &pl)==1 || - sscanf(buf,"%*d packets transmitted, %*d received, %d%% packet loss, time", &pl)==1 || - sscanf(buf,"%*d packets transmitted, %*d received, +%*d errors, %d%% packet loss", &pl) == 1 || - sscanf(buf,"%*d packets transmitted %*d received, +%*d errors, %d%% packet loss", &pl) == 1 - ) + output chld_out, chld_err; + char *p; + size_t mult = 1, i; + + if((result = np_runcmd(cmd, &chld_out, &chld_err, 0)) != 0) + result = STATE_WARNING; + + for(i = 0; i < chld_out.lines; i++) { + /* get the packet loss. Find the % sign and count backwards */ + if((p = memchr(chld_out.line[i], '%', chld_out.lens[i]))) { + p--; + pl = 0; + while(p != chld_out.line[i] && isdigit(*p)) { + pl += *p - '0' * mult; + mult *= 10; + p--; + } continue; - + } /* get the round trip average */ - else - if(sscanf(buf,"round-trip min/avg/max = %*f/%f/%*f",&rta)==1 || - sscanf(buf,"round-trip min/avg/max/mdev = %*f/%f/%*f/%*f",&rta)==1 || - sscanf(buf,"round-trip min/avg/max/sdev = %*f/%f/%*f/%*f",&rta)==1 || - sscanf(buf,"round-trip min/avg/max/stddev = %*f/%f/%*f/%*f",&rta)==1 || - sscanf(buf,"round-trip min/avg/max/std-dev = %*f/%f/%*f/%*f",&rta)==1 || - sscanf(buf,"round-trip (ms) min/avg/max = %*f/%f/%*f",&rta)==1 || - sscanf(buf,"round-trip (ms) min/avg/max/stddev = %*f/%f/%*f/%*f",&rta)==1 || - sscanf(buf,"rtt min/avg/max/mdev = %*f/%f/%*f/%*f ms",&rta)==1) - continue; + else { + if(sscanf(chld_out.line[i], "round-trip min/avg/max = %*f/%f/%*f", &rta) == 1 || + sscanf(chld_out.line[i], "round-trip min/avg/max/mdev = %*f/%f/%*f/%*f", &rta) == 1 || + sscanf(chld_out.line[i], "round-trip min/avg/max/sdev = %*f/%f/%*f/%*f", &rta) == 1 || + sscanf(chld_out.line[i], "round-trip min/avg/max/stddev = %*f/%f/%*f/%*f", &rta) == 1 || + sscanf(chld_out.line[i], "round-trip min/avg/max/std-dev = %*f/%f/%*f/%*f", &rta) == 1 || + sscanf(chld_out.line[i], "round-trip (ms) min/avg/max = %*f/%f/%*f", &rta) == 1 || + sscanf(chld_out.line[i], "round-trip (ms) min/avg/max/stddev = %*f/%f/%*f/%*f", &rta) == 1 || + sscanf(chld_out.line[i], "rtt min/avg/max/mdev = %*f/%f/%*f/%*f ms", &rta) == 1) + { + continue; + } + + result = max_state (result, error_scan (chld_out.line[i], addr)); + } } /* this is needed because there is no rta if all packets are lost */ @@ -442,19 +439,10 @@ rta = crta; /* check stderr, setting at least WARNING if there is output here */ - while (fgets (buf, MAX_INPUT_BUFFER - 1, child_stderr)) - if (! strstr(buf,"WARNING - no SO_TIMESTAMP support, falling back to SIOCGSTAMP")) - result = max_state (STATE_WARNING, error_scan (buf, addr)); - - (void) fclose (child_stderr); - - - /* close the pipe - WARNING if status is set */ - if (spclose (child_process)) - result = max_state (result, STATE_WARNING); - - if (warn_text == NULL) - warn_text = strdup(""); + if(chld_err.buflen > 0) { + if (! strstr(chld_err.line[0], "WARNING - no SO_TIMESTAMP support, falling back to SIOCGSTAMP")) + result = max_state (STATE_WARNING, error_scan (chld_err.line[0], addr)); + } return result; } @@ -462,7 +450,7 @@ int -error_scan (char buf[MAX_INPUT_BUFFER], const char *addr) +error_scan (const char *buf, const char *addr) { if (strstr (buf, "Network is unreachable")) die (STATE_CRITICAL, _("CRITICAL - Network unreachable (%s)"), addr); diff -urN ../nplg/plugins/check_procs.c ./plugins/check_procs.c --- ../nplg/plugins/check_procs.c 2005-06-03 19:35:45.000000000 +0200 +++ ./plugins/check_procs.c 2005-06-10 15:01:26.000000000 +0200 @@ -14,17 +14,17 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: check_procs.c,v 1.45 2005/06/03 13:53:43 seanius Exp $ + $Id: check_procs.c,v 1.3 2005/06/06 11:37:06 exon Exp $ ******************************************************************************/ const char *progname = "check_procs"; -const char *revision = "$Revision: 1.45 $"; +const char *revision = "$Revision: 1.3 $"; const char *copyright = "2000-2004"; const char *email = "nagiosplug-devel@lists.sourceforge.net"; #include "common.h" -#include "popen.h" +#include "runcmd.h" #include "utils.h" #include @@ -96,7 +96,7 @@ char procstat[8]; char procetime[MAX_INPUT_BUFFER] = { '\0' }; char *procargs; - char *temp_string; + output chld_out, chld_err; const char *zombie = "Z"; @@ -118,7 +118,7 @@ input_buffer = malloc (MAX_INPUT_BUFFER); procprog = malloc (MAX_INPUT_BUFFER); - asprintf (&metric_name, "PROCS"); + metric_name = "PROCS"; metric = METRIC_PROCS; if (process_arguments (argc, argv) == ERROR) @@ -136,27 +136,15 @@ if (verbose >= 2) printf (_("CMD: %s\n"), PS_COMMAND); - child_process = spopen (PS_COMMAND); - if (child_process == NULL) { - printf (_("Could not open pipe: %s\n"), PS_COMMAND); - return STATE_UNKNOWN; - } - - child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); - if (child_stderr == NULL) - printf (_("Could not open stderr for %s\n"), PS_COMMAND); - - /* flush first line */ - fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process); - while ( input_buffer[strlen(input_buffer)-1] != '\n' ) - fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process); - - while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { - asprintf (&input_line, "%s", input_buffer); - while ( input_buffer[strlen(input_buffer)-1] != '\n' ) { - fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process); - asprintf (&input_line, "%s%s", input_line, input_buffer); - } + result = np_runcmd(PS_COMMAND, &chld_out, &chld_err, 0); + if(result) { + printf (_("System call returned nonzero status\n")); + result = max_state (result, STATE_WARNING); + } + + /* start parsing on second line */ + for(i = 1; i < chld_out.lines; i++) { + input_line = chld_out.line[i]; if (verbose >= 3) printf ("%s", input_line); @@ -177,8 +165,7 @@ /* Some ps return full pathname for command. This removes path */ #ifdef HAVE_BASENAME - temp_string = strdup(procprog); - procprog = basename(temp_string); + procprog = strdup(basename(procprog)); #endif /* HAVE_BASENAME */ /* we need to convert the elapsed time to seconds */ @@ -248,27 +235,17 @@ } /* If we get anything on STDERR, at least set warning */ - while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) { - if (verbose) - printf ("STDERR: %s", input_buffer); + if(chld_err.buflen > 0) { result = max_state (result, STATE_WARNING); printf (_("System call sent warnings to stderr\n")); } - - (void) fclose (child_stderr); - - /* close the pipe */ - if (spclose (child_process)) { - printf (_("System call returned nonzero status\n")); - result = max_state (result, STATE_WARNING); - } if (found == 0) { /* no process lines parsed so return STATE_UNKNOWN */ printf (_("Unable to read output\n")); return result; } - if ( result == STATE_UNKNOWN ) + if ( result == STATE_UNKNOWN ) result = STATE_OK; /* Needed if procs found, but none match filter */ @@ -459,7 +436,7 @@ } usage4 (_("PCPU must be a float!")); case 'm': - asprintf (&metric_name, "%s", optarg); + metric_name = optarg; if ( strcmp(optarg, "PROCS") == 0) { metric = METRIC_PROCS; break; @@ -494,7 +471,7 @@ if (cmax == -1 && argv[c]) cmax = atoi (argv[c++]); if (statopts == NULL && argv[c]) { - asprintf (&statopts, "%s", argv[c++]); + statopts = argv[c++]; asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts); options |= STAT; } diff -urN ../nplg/plugins/check_snmp.c ./plugins/check_snmp.c --- ../nplg/plugins/check_snmp.c 2005-06-03 12:07:28.000000000 +0200 +++ ./plugins/check_snmp.c 2005-06-10 15:01:26.000000000 +0200 @@ -14,18 +14,18 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: check_snmp.c,v 1.57 2005/06/01 19:41:01 sghosh Exp $ + $Id: check_snmp.c,v 1.2 2005/06/05 21:55:26 exon Exp $ ******************************************************************************/ const char *progname = "check_snmp"; -const char *revision = "$Revision: 1.57 $"; +const char *revision = "$Revision: 1.2 $"; const char *copyright = "1999-2004"; const char *email = "nagiosplug-devel@lists.sourceforge.net"; #include "common.h" #include "utils.h" -#include "popen.h" +#include "runcmd.h" #define DEFAULT_COMMUNITY "public" #define DEFAULT_PORT "161" @@ -136,11 +136,12 @@ char *command_line = NULL; char *response = NULL; char *outbuff; - char *output; + char *msg; char *ptr = NULL; char *p2 = NULL; char *show = NULL; char type[8]; + output chld_out, chld_err; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); @@ -157,7 +158,7 @@ units = strdup (""); port = strdup (DEFAULT_PORT); outbuff = strdup (""); - output = strdup (""); + msg = strdup (""); delimiter = strdup (" = "); output_delim = strdup (DEFAULT_OUTPUT_DELIMITER); /* miblist = strdup (DEFAULT_MIBLIST); */ @@ -168,41 +169,25 @@ usage4 (_("Could not parse arguments")); /* create the command line to execute */ - if(usesnmpgetnext == TRUE) { - asprintf(&command_line, "%s -t %d -r %d -m %s -v %s %s %s:%s %s", - PATH_TO_SNMPGETNEXT, timeout_interval, retries, miblist, proto, - authpriv, server_address, port, oid); - }else{ - - asprintf (&command_line, "%s -t %d -r %d -m %s -v %s %s %s:%s %s", - PATH_TO_SNMPGET, timeout_interval, retries, miblist, proto, - authpriv, server_address, port, oid); - } - + asprintf(&command_line, "%s -t %d -r %d -m %s -v %s %s %s:%s %s", + usesnmpgetnext == TRUE ? PATH_TO_SNMPGETNEXT : PATH_TO_SNMPGET, + timeout_interval, retries, miblist, proto, + authpriv, server_address, port, oid); + if (verbose) printf ("%s\n", command_line); - /* run the command */ - child_process = spopen (command_line); - if (child_process == NULL) { - printf (_("Could not open pipe: %s\n"), command_line); - exit (STATE_UNKNOWN); - } - - child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); - if (child_stderr == NULL) { - printf (_("Could not open stderr for %s\n"), command_line); - } + if((np_runcmd(command_line, &chld_out, &chld_err, 0)) != 0 || chld_err.buflen) + result = STATE_WARNING; - while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) - asprintf (&output, "%s%s", output, input_buffer); + for(i = 0; (size_t)i < chld_out.lines; i++) + asprintf (&msg, "%s%s", msg, input_buffer); if (verbose) - printf ("%s\n", output); - - ptr = output; + printf ("%s\n", msg); + ptr = msg; strcat(perfstr, "| "); while (ptr) { char *foo; @@ -261,18 +246,11 @@ iresult = STATE_DEPENDENT; /* Process this block for integer comparisons */ - if (eval_method[i] & CRIT_GT || - eval_method[i] & CRIT_LT || - eval_method[i] & CRIT_GE || - eval_method[i] & CRIT_LE || - eval_method[i] & CRIT_EQ || - eval_method[i] & CRIT_NE || - eval_method[i] & WARN_GT || - eval_method[i] & WARN_LT || - eval_method[i] & WARN_GE || - eval_method[i] & WARN_LE || - eval_method[i] & WARN_EQ || - eval_method[i] & WARN_NE) { + if (eval_method[i] & (CRIT_GT | CRIT_LT | CRIT_GE | + CRIT_LE | CRIT_EQ | CRIT_NE | + WARN_GT | WARN_LT | WARN_GE | + WARN_LE | WARN_EQ | WARN_NE)) + { p2 = strpbrk (p2, "0123456789"); if (p2 == NULL) die (STATE_UNKNOWN,_("No valid data returned")); @@ -350,20 +328,6 @@ label, command_line); - /* WARNING if output found on stderr */ - if (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) - result = max_state (result, STATE_WARNING); - - /* close stderr */ - (void) fclose (child_stderr); - - /* close the pipe */ - if (spclose (child_process)) - result = max_state (result, STATE_WARNING); - -/* if (nunits == 1 || i == 1) */ -/* printf ("%s %s -%s %s\n", label, state_text (result), outbuff, units); */ -/* else */ printf ("%s %s -%s %s \n", label, state_text (result), outbuff, perfstr); return result; diff -urN ../nplg/plugins/check_swap.c ./plugins/check_swap.c --- ../nplg/plugins/check_swap.c 2005-01-24 08:29:54.000000000 +0100 +++ ./plugins/check_swap.c 2005-06-10 15:01:26.000000000 +0200 @@ -21,18 +21,18 @@ * * Copyright (c) 2000 Karl DeBisschop (kdebisschop@users.sourceforge.net) * - * $Id: check_swap.c,v 1.47 2005/01/19 21:14:47 tonvoon Exp $ + * $Id: check_swap.c,v 1.4 2005/06/06 11:37:06 exon Exp $ * *****************************************************************************/ const char *progname = "check_swap"; -const char *revision = "$Revision: 1.47 $"; +const char *revision = "$Revision: 1.4 $"; const char *copyright = "2000-2004"; const char *email = "nagiosplug-devel@lists.sourceforge.net"; #include "common.h" -#include "popen.h" #include "utils.h" +#include "runcmd.h" int check_swap (int usp, float free_swap); int process_arguments (int argc, char **argv); @@ -64,6 +64,8 @@ char *temp_buffer; char *swap_command; char *swap_format; + output chld_out, chld_err; + size_t i = 0; # else # ifdef HAVE_DECL_SWAPCTL int i=0, nswaps=0, swapctl_res=0; @@ -79,14 +81,13 @@ # endif #endif char str[32]; - char *status, *tmp_status; + char *status; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); status = strdup (""); - tmp_status = strdup (""); perf = strdup (""); if (process_arguments (argc, argv) == ERROR) @@ -146,15 +147,9 @@ if (verbose >= 3) printf (_("Format: %s\n"), swap_format); - child_process = spopen (swap_command); - if (child_process == NULL) { - printf (_("Could not open pipe: %s\n"), swap_command); - return STATE_UNKNOWN; - } - - child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); - if (child_stderr == NULL) - printf (_("Could not open stderr for %s\n"), swap_command); + /* run the command. set WARNING if non-zero return or output on stderr */ + if((np_runcmd(swap_command, &chld_out, &chld_err, 0)) || chld_err.buflen) + result = STATE_WARNING; sprintf (str, "%s", ""); /* read 1st line */ @@ -210,17 +205,6 @@ # ifdef _AIX } # endif - - /* If we get anything on STDERR, at least set warning */ - while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) - result = max_state (result, STATE_WARNING); - - /* close stderr */ - (void) fclose (child_stderr); - - /* close the pipe */ - if (spclose (child_process)) - result = max_state (result, STATE_WARNING); # else # ifdef CHECK_SWAP_SWAPCTL_SVR4 @@ -314,16 +298,19 @@ percent_used = 100 * ((double) used_swap) / ((double) total_swap); result = max_state (result, check_swap (percent_used, free_swap)); /* broken into two steps because of funkiness with builtin asprintf */ - asprintf (&tmp_status, _(" %d%% free (%.0f MB out of %.0f MB)"), - (100 - percent_used), free_swap, total_swap); - asprintf (&status, "%s%s", tmp_status, status); - - asprintf (&perf, "%s", perfdata ("swap", (long) free_swap, "MB", - TRUE, (long) max (warn_size/1024, warn_percent/100.0*total_swap), - TRUE, (long) max (crit_size/1024, crit_percent/100.0*total_swap), - TRUE, 0, - TRUE, (long) total_swap)); - printf ("SWAP %s:%s |%s\n", state_text (result), status, perf); + /* the breaking was removed because it was stupid. There's no reason + * to concatenate a string using asprintf() just to print it to stdout + * in the next statement. */ + printf (_("SWAP %s - %d%% free (%.0f MB out of %.0f MB) %s|"), + state_text (result), + (100 - percent_used), free_swap, total_swap, status); + + puts (perfdata ("swap", (long) free_swap, "MB", + TRUE, (long) max (warn_size/1024, warn_percent/100.0*total_swap), + TRUE, (long) max (crit_size/1024, crit_percent/100.0*total_swap), + TRUE, 0, + TRUE, (long) total_swap)); + return result; } @@ -383,7 +370,7 @@ } else if (strstr (optarg, ",") && strstr (optarg, "%") && - sscanf (optarg, "%.0f,%d%%", &warn_size, &warn_percent) == 2) { + sscanf (optarg, "%f,%d%%", &warn_size, &warn_percent) == 2) { break; } else if (strstr (optarg, "%") && @@ -400,7 +387,7 @@ } else if (strstr (optarg, ",") && strstr (optarg, "%") && - sscanf (optarg, "%.0f,%d%%", &crit_size, &crit_percent) == 2) { + sscanf (optarg, "%f,%d%%", &crit_size, &crit_percent) == 2) { break; } else if (strstr (optarg, "%") && diff -urN ../nplg/plugins/check_users.c ./plugins/check_users.c --- ../nplg/plugins/check_users.c 2005-01-05 21:53:22.000000000 +0100 +++ ./plugins/check_users.c 2005-06-10 15:01:26.000000000 +0200 @@ -14,17 +14,17 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: check_users.c,v 1.19 2004/12/25 23:17:44 opensides Exp $ + $Id: check_users.c,v 1.2 2005/06/05 21:55:26 exon Exp $ *****************************************************************************/ const char *progname = "check_users"; -const char *revision = "$Revision: 1.19 $"; +const char *revision = "$Revision: 1.2 $"; const char *copyright = "2000-2004"; const char *email = "nagiosplug-devel@lists.sourceforge.net"; #include "common.h" -#include "popen.h" +#include "runcmd.h" #include "utils.h" #define possibly_set(a,b) ((a) == 0 ? (b) : 0) @@ -41,52 +41,28 @@ { int users = -1; int result = STATE_UNKNOWN; - char input_buffer[MAX_INPUT_BUFFER]; - char *perf; + output chld_out, chld_err; + size_t i; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); - perf = strdup(""); - if (process_arguments (argc, argv) == ERROR) usage4 (_("Could not parse arguments")); /* run the command */ - child_process = spopen (WHO_COMMAND); - if (child_process == NULL) { - printf (_("Could not open pipe: %s\n"), WHO_COMMAND); - return STATE_UNKNOWN; - } - - child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); - if (child_stderr == NULL) - printf (_("Could not open stderr for %s\n"), WHO_COMMAND); - - users = 0; - - while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) { - - /* increment 'users' on all lines except total user count */ - if (input_buffer[0] != '#') { - users++; - continue; - } - - /* get total logged in users */ - if (sscanf (input_buffer, _("# users=%d"), &users) == 1) - break; - - } + result = np_runcmd(WHO_COMMAND, &chld_out, &chld_err, 0); + if(result != 0) + result = STATE_UNKNOWN; + + /* one user is listed per line, except when it begins with '#' */ + users = chld_out.lines; + for(i = 0; i < chld_out.lines; i++) + if (chld_out.line[0][0] == '#') users--; /* check STDERR */ - if (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) - result = possibly_set (result, STATE_UNKNOWN); - (void) fclose (child_stderr); - - /* close the pipe */ - if (spclose (child_process)) + if(chld_err.buflen > 0) result = possibly_set (result, STATE_UNKNOWN); /* else check the user count against warning and critical thresholds */ @@ -98,16 +74,12 @@ result = STATE_OK; if (result == STATE_UNKNOWN) - printf (_("Unable to read output\n")); - else { - asprintf(&perf, "%s", perfdata ("users", users, "", - TRUE, wusers, - TRUE, cusers, - TRUE, 0, - FALSE, 0)); - printf (_("USERS %s - %d users currently logged in |%s\n"), state_text (result), - users, perf); - } + die (STATE_UNKNOWN, _("Unable to read output\n")); + + printf (_("USERS %s - %d users currently logged in |%s\n"), + state_text (result), users, + perfdata("users", users, "", + TRUE, wusers, TRUE, cusers, TRUE, 0, FALSE, 0)); return result; } @@ -129,8 +101,10 @@ {0, 0, 0, 0} }; - if (argc < 2) - usage ("\n"); + if (argc < 2) { + print_usage (); + exit(STATE_UNKNOWN); + } while (1) { c = getopt_long (argc, argv, "+hVvc:w:", longopts, &option); diff -urN ../nplg/plugins/foo ./plugins/foo --- ../nplg/plugins/foo 1970-01-01 01:00:00.000000000 +0100 +++ ./plugins/foo 2005-06-10 15:05:25.000000000 +0200 @@ -0,0 +1,12 @@ +$Id: check_by_ssh.c,v 1.35 2004/12/25 12:09:19 opensides Exp $ +$Id: check_dig.c,v 1.40 2005/01/26 21:21:01 tonvoon Exp $ +$Id: check_dns.c,v 1.47 2004/12/30 00:41:39 opensides Exp $ +$Id: check_fping.c,v 1.24 2004/12/25 23:17:44 opensides Exp $ +$Id: check_load.c,v 1.28 2005/05/28 01:21:54 seanius Exp $ +$Id: check_nagios.c,v 1.26 2005/05/25 00:43:20 seanius Exp $ +$Id: check_ping.c,v 1.44 2005/05/25 14:25:55 sghosh Exp $ +$Id: check_procs.c,v 1.45 2005/06/03 13:53:43 seanius Exp $ +$Id: check_snmp.c,v 1.57 2005/06/01 19:41:01 sghosh Exp $ +$Id: check_users.c,v 1.19 2004/12/25 23:17:44 opensides Exp $ +$Id: negate.c,v 1.24 2004/12/25 23:17:44 opensides Exp $ +$Id: urlize.c,v 1.17 2004/12/25 23:17:44 opensides Exp $ diff -urN ../nplg/plugins/Makefile.am ./plugins/Makefile.am --- ../nplg/plugins/Makefile.am 2005-02-15 09:28:36.000000000 +0100 +++ ./plugins/Makefile.am 2005-06-10 15:01:26.000000000 +0200 @@ -24,7 +24,8 @@ check_nagios check_by_ssh check_dns check_nt check_ide_smart \ check_procs -EXTRA_DIST = t utils.c netutils.c popen.c utils.h netutils.h popen.h common.h \ +EXTRA_DIST = t common.h utils.c utils.h netutils.c netutils.h \ + runcmd.c runcmd.h \ getaddrinfo.c getaddrinfo.h gethostbyname.c gethostbyname.h PLUGINHDRS = common.h @@ -46,85 +47,85 @@ # the actual targets check_dhcp_LDADD = $(NETLIBS) -check_dig_LDADD = $(NETLIBS) popen.o -check_disk_LDADD = $(BASEOBJS) popen.o -check_dns_LDADD = $(NETLIBS) popen.o +check_dig_LDADD = $(NETLIBS) runcmd.o +check_disk_LDADD = $(BASEOBJS) runcmd.o +check_dns_LDADD = $(NETLIBS) runcmd.o check_dummy_LDADD = $(BASEOBJS) -check_fping_LDADD = $(NETLIBS) popen.o -check_game_LDADD = $(BASEOBJS) popen.o +check_fping_LDADD = $(NETLIBS) runcmd.o +check_game_LDADD = $(BASEOBJS) runcmd.o check_http_LDADD = $(NETLIBS) $(SSLLIBS) -check_hpjd_LDADD = $(NETLIBS) popen.o +check_hpjd_LDADD = $(NETLIBS) runcmd.o check_icmp_LDADD = $(SOCKETLIBS) check_ldap_LDADD = $(NETLIBS) $(LDAPLIBS) -check_load_LDADD = $(BASEOBJS) popen.o +check_load_LDADD = $(BASEOBJS) runcmd.o check_mrtg_LDADD = $(BASEOBJS) check_mrtgtraf_LDADD = $(BASEOBJS) check_mysql_LDADD = $(NETLIBS) $(MYSQLLIBS) -check_nagios_LDADD = $(BASEOBJS) popen.o +check_nagios_LDADD = $(BASEOBJS) runcmd.o check_nt_LDADD = $(NETLIBS) check_nwstat_LDADD = $(NETLIBS) check_overcr_LDADD = $(NETLIBS) check_pgsql_LDADD = $(NETLIBS) $(PGLIBS) -check_ping_LDADD = $(NETLIBS) popen.o -check_procs_LDADD = $(BASEOBJS) popen.o +check_ping_LDADD = $(NETLIBS) runcmd.o +check_procs_LDADD = $(BASEOBJS) runcmd.o check_radius_LDADD = $(NETLIBS) $(RADIUSLIBS) check_real_LDADD = $(NETLIBS) -check_snmp_LDADD = $(BASEOBJS) popen.o +check_snmp_LDADD = $(BASEOBJS) runcmd.o check_smtp_LDADD = $(NETLIBS) $(SSLLIBS) check_ssh_LDADD = $(NETLIBS) -check_swap_LDADD = $(BASEOBJS) popen.o +check_swap_LDADD = $(BASEOBJS) runcmd.o check_tcp_LDADD = $(NETLIBS) $(SSLLIBS) check_time_LDADD = $(NETLIBS) check_udp_LDADD = $(NETLIBS) check_ups_LDADD = $(NETLIBS) -check_users_LDADD = $(BASEOBJS) popen.o -check_by_ssh_LDADD = $(NETLIBS) popen.o +check_users_LDADD = $(BASEOBJS) runcmd.o +check_by_ssh_LDADD = $(NETLIBS) runcmd.o check_ide_smart_LDADD = $(BASEOBJS) -negate_LDADD = $(BASEOBJS) popen.o -urlize_LDADD = $(BASEOBJS) popen.o +negate_LDADD = $(BASEOBJS) runcmd.o +urlize_LDADD = $(BASEOBJS) runcmd.o check_dhcp_DEPENDENCIES = check_dhcp.c $(NETOBJS) $(DEPLIBS) -check_dig_DEPENDENCIES = check_dig.c $(NETOBJS) popen.o $(DEPLIBS) -check_disk_DEPENDENCIES = check_disk.c $(BASEOBJS) popen.o $(DEPLIBS) -check_dns_DEPENDENCIES = check_dns.c $(NETOBJS) popen.o $(DEPLIBS) +check_dig_DEPENDENCIES = check_dig.c $(NETOBJS) runcmd.o $(DEPLIBS) +check_disk_DEPENDENCIES = check_disk.c $(BASEOBJS) runcmd.o $(DEPLIBS) +check_dns_DEPENDENCIES = check_dns.c $(NETOBJS) runcmd.o $(DEPLIBS) check_dummy_DEPENDENCIES = check_dummy.c $(DEPLIBS) -check_fping_DEPENDENCIES = check_fping.c $(NETOBJS) popen.o $(DEPLIBS) +check_fping_DEPENDENCIES = check_fping.c $(NETOBJS) runcmd.o $(DEPLIBS) check_game_DEPENDENCIES = check_game.c $(DEPLIBS) check_http_DEPENDENCIES = check_http.c $(NETOBJS) $(DEPLIBS) -check_hpjd_DEPENDENCIES = check_hpjd.c $(NETOBJS) popen.o $(DEPLIBS) +check_hpjd_DEPENDENCIES = check_hpjd.c $(NETOBJS) runcmd.o $(DEPLIBS) check_icmp_DEPENDENCIES = check_icmp.c check_ide_smart_DEPENDENCIES = check_ide_smart.c $(BASEOBJS) $(DEPLIBS) check_ldap_DEPENDENCIES = check_ldap.c $(NETOBJS) $(DEPLIBS) -check_load_DEPENDENCIES = check_load.c $(BASEOBJS) popen.o $(DEPLIBS) +check_load_DEPENDENCIES = check_load.c $(BASEOBJS) runcmd.o $(DEPLIBS) check_mrtg_DEPENDENCIES = check_mrtg.c $(DEPLIBS) check_mrtgtraf_DEPENDENCIES = check_mrtgtraf.c $(DEPLIBS) check_mysql_DEPENDENCIES = check_mysql.c $(NETOBJS) $(DEPLIBS) -check_nagios_DEPENDENCIES = check_nagios.c $(BASEOBJS) popen.o $(DEPLIBS) +check_nagios_DEPENDENCIES = check_nagios.c $(BASEOBJS) runcmd.o $(DEPLIBS) check_nt_DEPENDENCIES = check_nt.c $(NETOBJS) $(DEPLIBS) check_nwstat_DEPENDENCIES = check_nwstat.c $(NETOBJS) $(DEPLIBS) check_overcr_DEPENDENCIES = check_overcr.c $(NETOBJS) $(DEPLIBS) check_pgsql_DEPENDENCIES = check_pgsql.c $(NETOBJS) $(DEPLIBS) -check_ping_DEPENDENCIES = check_ping.c $(NETOBJS) popen.o $(DEPLIBS) -check_procs_DEPENDENCIES = check_procs.c $(BASEOBJS) popen.o $(DEPLIBS) +check_ping_DEPENDENCIES = check_ping.c $(NETOBJS) runcmd.o $(DEPLIBS) +check_procs_DEPENDENCIES = check_procs.c $(BASEOBJS) runcmd.o $(DEPLIBS) check_radius_DEPENDENCIES = check_radius.c $(NETOBJS) $(DEPLIBS) check_real_DEPENDENCIES = check_real.c $(NETOBJS) $(DEPLIBS) -check_snmp_DEPENDENCIES = check_snmp.c $(BASEOBJS) popen.o $(DEPLIBS) +check_snmp_DEPENDENCIES = check_snmp.c $(BASEOBJS) runcmd.o $(DEPLIBS) check_smtp_DEPENDENCIES = check_smtp.c $(NETOBJS) $(DEPLIBS) check_ssh_DEPENDENCIES = check_ssh.c $(NETOBJS) $(DEPLIBS) -check_swap_DEPENDENCIES = check_swap.c $(BASEOBJS) popen.o $(DEPLIBS) +check_swap_DEPENDENCIES = check_swap.c $(BASEOBJS) runcmd.o $(DEPLIBS) check_tcp_DEPENDENCIES = check_tcp.c $(NETOBJS) $(DEPLIBS) check_time_DEPENDENCIES = check_time.c $(NETOBJS) $(DEPLIBS) check_udp_DEPENDENCIES = check_udp.c $(NETOBJS) $(DEPLIBS) check_ups_DEPENDENCIES = check_ups.c $(NETOBJS) $(DEPLIBS) -check_users_DEPENDENCIES = check_users.c $(BASEOBJS) popen.o $(DEPLIBS) -check_by_ssh_DEPENDENCIES = check_by_ssh.c $(NETOBJS) popen.o $(DEPLIBS) -negate_DEPENDENCIES = negate.c $(BASEOBJS) popen.o $(DEPLIBS) -urlize_DEPENDENCIES = urlize.c $(BASEOBJS) popen.o $(DEPLIBS) +check_users_DEPENDENCIES = check_users.c $(BASEOBJS) runcmd.o $(DEPLIBS) +check_by_ssh_DEPENDENCIES = check_by_ssh.c $(NETOBJS) runcmd.o $(DEPLIBS) +negate_DEPENDENCIES = negate.c $(BASEOBJS) runcmd.o $(DEPLIBS) +urlize_DEPENDENCIES = urlize.c $(BASEOBJS) runcmd.o $(DEPLIBS) ############################################################################## # secondary dependencies -popen.o: popen.c popen.h $(PLUGINHDRS) +runcmd.o: runcmd.c runcmd.h $(PLUGINHDRS) utils.o: utils.c utils.h $(PLUGINHDRS) diff -urN ../nplg/plugins/negate.c ./plugins/negate.c --- ../nplg/plugins/negate.c 2005-01-05 21:53:22.000000000 +0100 +++ ./plugins/negate.c 2005-06-10 15:01:26.000000000 +0200 @@ -14,7 +14,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: negate.c,v 1.24 2004/12/25 23:17:44 opensides Exp $ + $Id: negate.c,v 1.2 2005/06/05 21:55:26 exon Exp $ @@-
@@ -54,7 +54,7 @@ ******************************************************************************/ const char *progname = "negate"; -const char *revision = "$Revision: 1.24 $"; +const char *revision = "$Revision: 1.2 $"; const char *copyright = "2002-2004"; const char *email = "nagiosplug-devel@lists.sourceforge.net"; @@ -62,7 +62,7 @@ #include "common.h" #include "utils.h" -#include "popen.h" +#include "runcmd.h" char *command_line; @@ -76,8 +76,9 @@ int main (int argc, char **argv) { - int found = 0, result = STATE_UNKNOWN; - char *buf; + int result = STATE_UNKNOWN; + output chld_out, chld_err; + size_t i; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); @@ -92,43 +93,26 @@ (void) alarm ((unsigned) timeout_interval); - child_process = spopen (command_line); - if (child_process == NULL) - die (STATE_UNKNOWN, _("Could not open pipe: %s\n"), command_line); - - child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); - - if (child_stderr == NULL) { - printf (_("Could not open stderr for %s\n"), command_line); - } - - buf = malloc(MAX_INPUT_BUFFER); - while (fgets (buf, MAX_INPUT_BUFFER - 1, child_process)) { - found++; - printf ("%s", buf); - } - - if (!found) + result = np_runcmd(command_line, &chld_out, &chld_err, 0); + if (!chld_out.buflen) die (STATE_UNKNOWN, _("%s problem - No data received from host\nCMD: %s\n"),\ argv[0], command_line); - /* close the pipe */ - result = spclose (child_process); + for(i = 0; i < chld_out.lines; i++) + printf("%s", chld_out.line[i]); /* WARNING if output found on stderr */ - if (fgets (buf, MAX_INPUT_BUFFER - 1, child_stderr)) + if (chld_err.buflen != 0) result = max_state (result, STATE_WARNING); - /* close stderr */ - (void) fclose (child_stderr); - if (result == STATE_OK) exit (STATE_CRITICAL); - else if (result == STATE_CRITICAL) + + if (result == STATE_CRITICAL) exit (EXIT_SUCCESS); - else - exit (result); + + exit (result); } /****************************************************************************** diff -urN ../nplg/plugins/runcmd.c ./plugins/runcmd.c --- ../nplg/plugins/runcmd.c 1970-01-01 01:00:00.000000000 +0100 +++ ./plugins/runcmd.c 2005-06-10 15:01:26.000000000 +0200 @@ -0,0 +1,339 @@ +/* + * $Id: runcmd.c,v 1.1 2005/06/05 21:55:26 exon Exp $ + * + * A simple interface to executing programs from other programs, using an + * optimized and safe popen()-like implementation. It is considered safe + * in that no shell needs to be spawned and the environment passed to the + * execve()'d program is essentially empty. + * + * + * The code in this file is a derivative of popen.c which in turn was taken + * from "Advanced Programming for the Unix Environment" by W. Richard Stevens. + * + * Care has been taken to make sure the functions are async-safe. The one + * function which isn't is np_runcmd_init() which it doesn't make sense to + * call twice anyway, so the api as a whole should be considered async-safe. + * + */ + +/** includes **/ +#include "runcmd.h" +#ifdef HAVE_SYS_WAIT_H +# include +#endif + +/** macros **/ +#ifndef WEXITSTATUS +# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif + +#ifndef WIFEXITED +# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif + +/* 4.3BSD Reno doesn't define SIG_ERR */ +#if defined(SIG_IGN) && !defined(SIG_ERR) +# define SIG_ERR ((Sigfunc *)-1) +#endif + +/* This variable must be global, since there's no way the caller + * can forcibly slay a dead or ungainly running program otherwise. + * Multithreading apps and plugins can initialize it (via NP_RUNCMD_INIT) + * in an async safe manner PRIOR to calling np_runcmd() for the first time. + * + * The check for initialized values is atomic and can + * occur in any number of threads simultaneously. */ +static pid_t *np_pids = NULL; + +/* If OPEN_MAX isn't defined, we try the sysconf syscall first. + * If that fails, we fall back to an educated guess which is accurate + * on Linux and some other systems. There's no guarantee that our guess is + * adequate and the program will die with SIGSEGV if it isn't and the + * upper boundary is breached. */ +#ifdef OPEN_MAX +# define maxfd OPEN_MAX +#else +# ifndef _SC_OPEN_MAX /* sysconf macro unavailable, so guess */ +# define maxfd 256 +# else +static int maxfd = 0; +# endif /* _SC_OPEN_MAX */ +#endif /* OPEN_MAX */ + + +/** prototypes **/ +static int np_runcmd_open(const char *, int *, int *) + __attribute__((__nonnull__(1, 2, 3))); + +static int np_fetch_output(int, output *, int) + __attribute__((__nonnull__(2))); + +static int np_runcmd_close(int); + +/* imported from utils.h */ +extern void die (int, const char *, ...) + __attribute__((__noreturn__,__format__(__printf__, 2, 3))); + + +/* this function is NOT async-safe. It is exported so multithreaded + * plugins (or other apps) can call it prior to running any commands + * through this api and thus achieve async-safeness throughout the api */ +void np_runcmd_init(void) +{ +#if !defined(OPEN_MAX) && defined(_SC_OPEN_MAX) + if(!maxfd) { + if((maxfd = sysconf(_SC_OPEN_MAX)) < 0) { + /* possibly log or emit a warning here, since there's no + * guarantee that our guess at maxfd will be adequate */ + maxfd = 256; + } + } +#endif + + if(!np_pids) np_pids = calloc(maxfd, sizeof(pid_t)); +} + + +/* Start running a command */ +static int +np_runcmd_open(const char *cmdstring, int *pfd, int *pfderr) +{ + char *env[2]; + char *cmd = NULL; + char **argv = NULL; + char *str; + int argc; + size_t cmdlen; + pid_t pid; +#ifdef RLIMIT_CORE + struct rlimit limit; +#endif + + int i = 0; + + if(!np_pids) NP_RUNCMD_INIT; + + env[0] = strdup("LC_ALL=C"); + env[1] = '\0'; + + /* if no command was passed, return with no error */ + if (cmdstring == NULL) + return -1; + + /* make copy of command string so strtok() doesn't silently modify it */ + /* (the calling program may want to access it later) */ + cmdlen = strlen(cmdstring); + cmd = malloc(cmdlen + 1); + if (cmd == NULL) return -1; + memcpy(cmd, cmdstring, cmdlen); + + /* This is not a shell, so we don't handle "???" */ + if (strstr (cmdstring, "\"")) return -1; + + /* allow single quotes, but only if non-whitesapce doesn't occur on both sides */ + if (strstr (cmdstring, " ' ") || strstr (cmdstring, "'''")) + return -1; + + /* each arg must be whitespace-separated, so args can be a maximum + * of (len / 2) + 1. We add 1 extra to the mix for NULL termination */ + argc = (cmdlen >> 1) + 2; + argv = calloc(sizeof(char *), argc); + + if (argv == NULL) { + printf (_("Could not malloc argv array in popen()\n")); + return -1; + } + + /* get command arguments (stupidly, but fairly quickly) */ + while (cmd) { + str = cmd; + str += strspn (str, " \t\r\n"); /* trim any leading whitespace */ + + if (strstr (str, "'") == str) { /* handle SIMPLE quoted strings */ + str++; + if (!strstr (str, "'")) return -1; /* balanced? */ + cmd = 1 + strstr (str, "'"); + str[strcspn (str, "'")] = 0; + } + else { + if (strpbrk (str, " \t\r\n")) { + cmd = 1 + strpbrk (str, " \t\r\n"); + str[strcspn (str, " \t\r\n")] = 0; + } + else { + cmd = NULL; + } + } + + if (cmd && strlen (cmd) == strspn (cmd, " \t\r\n")) + cmd = NULL; + + argv[i++] = str; + } + + if (pipe(pfd) < 0 || pipe(pfderr) < 0 || (pid = fork()) < 0) + return -1; /* errno set by the failing function */ + + /* child runs exceve() and _exit. */ + if (pid == 0) { +#ifdef RLIMIT_CORE + /* the program we execve shouldn't leave core files */ + getrlimit (RLIMIT_CORE, &limit); + limit.rlim_cur = 0; + setrlimit (RLIMIT_CORE, &limit); +#endif + close (pfd[0]); + if (pfd[1] != STDOUT_FILENO) { + dup2 (pfd[1], STDOUT_FILENO); + close (pfd[1]); + } + close (pfderr[0]); + if (pfderr[1] != STDERR_FILENO) { + dup2 (pfderr[1], STDERR_FILENO); + close (pfderr[1]); + } + + /* close all descriptors in np_pids[] + * This is executed in a separate address space (pure child), + * so we don't have to worry about async safety */ + for (i = 0; i < maxfd; i++) + if(np_pids[i] > 0) + close (i); + + execve (argv[0], argv, env); + _exit (0); + } + + /* parent picks up execution here */ + /* close childs descriptors in our address space */ + close(pfd[1]); + close(pfderr[1]); + + /* tag our file's entry in the pid-list and return it */ + np_pids[pfd[0]] = pid; + + return pfd[0]; +} + + +static int +np_runcmd_close(int fd) +{ + int status; + pid_t pid; + + /* make sure this fd was opened by popen() */ + if(fd < 0 || fd > maxfd || !np_pids || (pid = np_pids[fd]) == 0) + return -1; + + np_pids[fd] = 0; + if (close (fd) == -1) return -1; + + /* EINTR is ok (sort of), everything else is bad */ + while (waitpid (pid, &status, 0) < 0) + if (errno != EINTR) return -1; + + /* return child's termination status */ + return (WIFEXITED(status)) ? WEXITSTATUS(status) : -1; +} + + +void +popen_timeout_alarm_handler (int signo) +{ + size_t i; + + if (signo == SIGALRM) + puts(_("CRITICAL - Plugin timed out while executing system call\n")); + + if(np_pids) for(i = 0; i < maxfd; i++) { + if(np_pids[i] != 0) kill(np_pids[i], SIGKILL); + } + + exit (STATE_CRITICAL); +} + + +static int +np_fetch_output(int fd, output *op, int flags) +{ + size_t len = 0, i = 0; + size_t rsf = 6, ary_size = 0; /* rsf = right shift factor, dec'ed uncond once */ + char *buf = NULL; + int ret; + char tmpbuf[4096]; + + op->buf = NULL; + op->buflen = 0; + while((ret = read(fd, tmpbuf, sizeof(tmpbuf))) > 0) { + len = (size_t)ret; + op->buf = realloc(op->buf, op->buflen + len + 1); + memcpy(op->buf + op->buflen, tmpbuf, len); + op->buflen += len; + i++; + } + + if(ret < 0) { + printf("read() returned %d: %s\n", ret, strerror(errno)); + return ret; + } + + if(!op->buf || !op->buflen) return 0; + + /* some plugins may want to keep output unbroken */ + if(flags & RUNCMD_NO_ARRAYS) + return op->buflen; + + /* and some may want both (*sigh*) */ + if(flags & RUNCMD_NO_ASSOC) { + buf = malloc(op->buflen); + memcpy(buf, op->buf, op->buflen); + } + else buf = op->buf; + + op->line = NULL; + op->lens = NULL; + len = i = 0; + while(i < op->buflen) { + /* make sure we have enough memory */ + if(len >= ary_size) { + ary_size = op->buflen >> --rsf; + op->line = realloc(op->line, ary_size * sizeof(char *)); + op->lens = realloc(op->lens, ary_size * sizeof(size_t)); + } + + /* set the pointer to the string */ + op->line[len] = &buf[i]; + + /* hop to next newline or end of buffer */ + while(buf[i] != '\n' && i < op->buflen) i++; + buf[i] = '\0'; + + /* calculate the string length using pointer difference */ + op->lens[len] = (size_t)&buf[i] - (size_t)op->line[len]; + + len++; + i++; + } + + return len; +} + + +int +np_runcmd(const char *cmd, output *out, output *err, int flags) +{ + int fd, pfd_out[2], pfd_err[2]; + + /* initialize the structs */ + if(out) memset(out, 0, sizeof(output)); + if(err) memset(err, 0, sizeof(output)); + + if((fd = np_runcmd_open(cmd, pfd_out, pfd_err)) == -1) + die (STATE_UNKNOWN, _("Could not open pipe: %s\n"), cmd); + + if(out) out->lines = np_fetch_output(pfd_out[0], out, flags); + if(err) err->lines = np_fetch_output(pfd_err[0], err, flags); + + return np_runcmd_close(fd); +} diff -urN ../nplg/plugins/runcmd.h ./plugins/runcmd.h --- ../nplg/plugins/runcmd.h 1970-01-01 01:00:00.000000000 +0100 +++ ./plugins/runcmd.h 2005-06-10 15:01:26.000000000 +0200 @@ -0,0 +1,39 @@ +/* + * $Id: runcmd.h,v 1.1 2005/06/05 21:55:26 exon Exp $ + * + * Author: Andreas Ericsson + * + * Copyright: GNU GPL v2 or any later version. + * + */ + +#ifndef NAGIOSPLUG_RUNCMD_H +#define NAGIOSPLUG_RUNCMD_H + +#include "common.h" + +/** types **/ +struct output { + char *buf; /* output buffer */ + size_t buflen; /* output buffer content length */ + char **line; /* array of lines (points to buf) */ + size_t *lens; /* string lengths */ + size_t lines; /* lines of output */ +}; + +typedef struct output output; + +/** prototypes **/ +int np_runcmd(const char *, output *, output *, int); +void popen_timeout_alarm_handler(int) + __attribute__((__noreturn__)); + +/* only multi-threaded plugins need to bother with this */ +void np_runcmd_init(void); +#define NP_RUNCMD_INIT np_runcmd_init() + +/* possible flags for np_runcmd()'s fourth argument */ +#define RUNCMD_NO_ARRAYS 0x01 /* don't populate arrays at all */ +#define RUNCMD_NO_ASSOC 0x02 /* output.line won't point to buf */ + +#endif /* NAGIOSPLUG_RUNCMD_H */ diff -urN ../nplg/plugins/urlize.c ./plugins/urlize.c --- ../nplg/plugins/urlize.c 2005-01-05 21:53:23.000000000 +0100 +++ ./plugins/urlize.c 2005-06-10 15:01:26.000000000 +0200 @@ -14,18 +14,18 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: urlize.c,v 1.17 2004/12/25 23:17:44 opensides Exp $ + $Id: urlize.c,v 1.2 2005/06/05 21:55:26 exon Exp $ ******************************************************************************/ const char *progname = "urlize"; -const char *revision = "$Revision: 1.17 $"; +const char *revision = "$Revision: 1.2 $"; const char *copyright = "2000-2004"; const char *email = "nagiosplug-devel@lists.sourceforge.net"; #include "common.h" #include "utils.h" -#include "popen.h" +#include "runcmd.h" void print_help (void); void print_usage (void); @@ -33,10 +33,11 @@ int main (int argc, char **argv) { - int found = 0, result = STATE_UNKNOWN; + int result = STATE_UNKNOWN; char *url = NULL; char *cmd; - char *buf; + output chld_out, chld_err; + size_t i; int c; int option = 0; @@ -67,55 +68,37 @@ exit (EXIT_SUCCESS); break; case 'u': - url = strdup (argv[optind]); + url = optarg; break; case '?': default: - usage2 (_("Unknown argument"), optarg); + usage3 (_("Unknown argument"), c); } } - if (url == NULL) - url = strdup (argv[optind++]); + if (url == NULL && optind < argc - 1) + url = argv[optind++]; cmd = strdup (argv[optind++]); for (c = optind; c < argc; c++) { asprintf (&cmd, "%s %s", cmd, argv[c]); } - child_process = spopen (cmd); - if (child_process == NULL) { - printf (_("Could not open pipe: %s\n"), cmd); - exit (STATE_UNKNOWN); - } - - child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); - if (child_stderr == NULL) { - printf (_("Could not open stderr for %s\n"), cmd); - } + result = np_runcmd(cmd, &chld_out, &chld_err, 0); + printf ("", url); - buf = malloc(MAX_INPUT_BUFFER); - printf ("", argv[1]); - while (fgets (buf, MAX_INPUT_BUFFER - 1, child_process)) { - found++; - printf ("%s", buf); - } - - if (!found) + if (!chld_out.lines) die (STATE_UNKNOWN, _("%s UNKNOWN - No data received from host\nCMD: %s\n"), argv[0], cmd); - /* close the pipe */ - result = spclose (child_process); + for(i = 0; i < chld_out.lines; i++) + printf("%s", chld_out.line[i]); /* WARNING if output found on stderr */ - if (fgets (buf, MAX_INPUT_BUFFER - 1, child_stderr)) + if (chld_err.buflen) result = max_state (result, STATE_WARNING); - /* close stderr */ - (void) fclose (child_stderr); - printf ("\n"); return result; }