[Nagiosplug-devel] np_runcmd framework

Andreas Ericsson ae at op5.se
Fri Jun 10 06:33:50 CEST 2005


Just a thought; This patch requires the nagiosplug-common_h-sanity.diff 
I sent in a week or so ago. One of the problems of maintaining and 
testing with a separate CVS repository, I suppose.

Cheers.

Andreas Ericsson wrote:
> Ahoy.
> 
> I've completed the np_runcmd framework and tested it on Linux (FC3 and 
> Owl-current) and FreeBSD. It seems to work splendidly, providing a 
> slight speedup for some things and quite a bit smaller code.
> 
> Also included in this patch is a major cleanup and overhaul for 
> check_hpjd. I haven't been able to test it as I don't have a hpjd 
> printer, but the theory behind it is sound and I'm confident it will 
> work as expected. It reduces the LOC count by about 100 lines (25%) and 
> uses more portable and easier to parse snmpget syntax.
> 
> As I don't have cvs commit access I was forced to fork this off into a 
> repository of my own (hence all the $Id: $ updates in the diff). I will 
> keep working on that repository and see what possibilities there are for 
> backsyncing with the official project. Sorry about that, but my 
> work-description includes fixing and improving on the plugins and the 
> number of patches I had to keep track of quickly turned out to be 
> unmanagable without an SCM where I could commit things occasionally.
> 
> I'll add this to the tracker as well (*sigh*).
> 
> 
> ------------------------------------------------------------------------
> 
> 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 at 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 at 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 <server port>] [-T <query type>]\n\
> -                  [-w <warning interval>] [-c <critical interval>] [-t <timeout>]\n\
> -                  [-a <expected answer address>] [-v]\n", progname);
> +              [-w <warning interval>] [-c <critical interval>] [-t <timeout>]\n\
> +              [-a <expected answer address>] [-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 at 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 at 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 at 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 at 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 at lists.sourceforge.net";
>  
>  #include "common.h"
>  #include "utils.h"
> -#include "popen.h"
> +#include "runcmd.h"
>  
>  #ifdef HAVE_SYS_LOADAVG_H
>  #include <sys/loadavg.h>
> @@ -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 at 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 at 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 ("<A HREF='%s/traceroute.cgi?%s'>", 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 ("</A>");
>  		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 at lists.sourceforge.net";
>  
>  #include "common.h"
> -#include "popen.h"
> +#include "runcmd.h"
>  #include "utils.h"
>  
>  #include <pwd.h>
> @@ -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 at 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 at 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 at 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 at 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 $
>  
>  @@-<article>
>  
> @@ -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 at 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 <sys/wait.h>
> +#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 <signal.h> 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 <ae at op5.se>
> + *
> + * 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 at 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 ("<A href=\"%s\">", url);
>  
> -	buf = malloc(MAX_INPUT_BUFFER);
> -	printf ("<A href=\"%s\">", 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</A>\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 ("</A>\n");
>  	return result;
>  }

-- 
Andreas Ericsson                   andreas.ericsson at op5.se
OP5 AB                             www.op5.se
Lead Developer




More information about the Devel mailing list