diff -urN ../nplg/plugins/check_by_ssh.c ./plugins/check_by_ssh.c
--- ../nplg/plugins/check_by_ssh.c	2005-01-05 21:53:11.000000000 +0100
+++ ./plugins/check_by_ssh.c	2005-06-10 15:01:26.000000000 +0200
@@ -14,19 +14,19 @@
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
- $Id: check_by_ssh.c,v 1.35 2004/12/25 12:09:19 opensides Exp $
+ $Id: check_by_ssh.c,v 1.3 2005/06/06 11:37:06 exon Exp $
  
  *****************************************************************************/
  
 const char *progname = "check_by_ssh";
-const char *revision = "$Revision: 1.35 $";
+const char *revision = "$Revision: 1.3 $";
 const char *copyright = "2000-2004";
 const char *email = "nagiosplug-devel@lists.sourceforge.net";
 
 #include "common.h"
 #include "netutils.h"
 #include "utils.h"
-#include "popen.h"
+#include "runcmd.h"
 
 int process_arguments (int, char **);
 int validate_arguments (void);
@@ -49,15 +49,15 @@
 main (int argc, char **argv)
 {
 
-	char input_buffer[MAX_INPUT_BUFFER];
 	char *result_text;
 	char *status_text;
-	char *output;
+	char *msg;
 	char *eol = NULL;
 	int cresult;
 	int result = STATE_UNKNOWN;
 	time_t local_time;
 	FILE *fp = NULL;
+	struct output chld_out, chld_err;
 
 	remotecmd = strdup ("");
 	comm = strdup (SSH_COMMAND);
@@ -82,48 +82,22 @@
 	if (verbose)
 		printf ("%s\n", comm);
 
-	child_process = spopen (comm);
-
-	if (child_process == NULL) {
-		printf (_("Could not open pipe: %s\n"), comm);
-		return STATE_UNKNOWN;
-	}
-
-
-	/* open STDERR  for spopen */
-	child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
-	if (child_stderr == NULL) {
-		printf (_("Could not open stderr for %s\n"), SSH_COMMAND);
-	}
-
+	result = np_runcmd(comm, &chld_out, &chld_err, 0);
 
 	/* build up results from remote command in result_text */
-	while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process))
-		asprintf (&result_text, "%s%s", result_text, input_buffer);
+	if(skip_lines && skip_lines < chld_out.lines)
+		result_text = chld_out.line[skip_lines];
+	else
+		result_text = chld_out.line[0];
 
 	/* WARNING if output found on stderr */
-	while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
-		if (skip_lines > 0) {
-			if (input_buffer[strlen(input_buffer)-1] == '\n') {
-				skip_lines--;
-			}
-		} else {
-			printf ("%s", input_buffer);
-			result = STATE_WARNING;
-		}
+	if(chld_err.buflen) {
+		printf("%s\n", chld_err.line[0]);
+		return STATE_WARNING;
 	}
-	(void) fclose (child_stderr);
-	if (result == STATE_WARNING)
-		return result;
-
-
-	/* close the pipe */
-	result = spclose (child_process);
-
 
 	/* process output */
 	if (passive) {
-
 		if (!(fp = fopen (outputfile, "a"))) {
 			printf (_("SSH WARNING: could not open %s\n"), outputfile);
 			exit (STATE_UNKNOWN);
@@ -137,19 +111,19 @@
 				printf ("%s", result_text);
 				return result;
 			}
-			asprintf (&output, "%s", result_text);
+			asprintf (&msg, "%s", result_text);
 			result_text = strnl (status_text);
-			eol = strpbrk (output, "\r\n");
+			eol = strpbrk (msg, "\r\n");
 			if (eol != NULL)
 				eol[0] = 0;
 			if (service[commands] && status_text
-					&& sscanf (status_text, "STATUS CODE: %d", &cresult) == 1) {
+			    && sscanf (status_text, "STATUS CODE: %d", &cresult) == 1)
+			{
 				fprintf (fp, "[%d] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n",
-								 (int) local_time, host_shortname, service[commands++], cresult,
-								 output);
+				         (int) local_time, host_shortname, service[commands++],
+				         cresult, msg);
 			}
 		}
-
 	}
 
 
@@ -206,7 +180,7 @@
 
 	while (1) {
 		c = getopt_long (argc, argv, "Vvh1246ft:H:O:p:i:u:l:C:S:n:s:", longopts,
-									 &option);
+		                 &option);
 
 		if (c == -1 || c == EOF)
 			break;
@@ -244,25 +218,27 @@
 			passive = TRUE;
 			break;
 		case 's':									/* description of service to check */
-			service = realloc (service, (++services) * sizeof(char *));
 			p1 = optarg;
+			service = realloc (service, (++services) * sizeof(char *));
 			while ((p2 = index (p1, ':'))) {
 				*p2 = '\0';
-				asprintf (&service[services-1], "%s", p1);
+				service[services - 1] = p1;
 				service = realloc (service, (++services) * sizeof(char *));
 				p1 = p2 + 1;
 			}
-			asprintf (&service[services-1], "%s", p1);
+			service[services - 1] = p1;
 			break;
 		case 'n':									/* short name of host in nagios configuration */
 			host_shortname = optarg;
 			break;
+
 		case 'u':
 			c = 'l';
 		case 'l':									/* login name */
 		case 'i':									/* identity */
 			asprintf (&comm, "%s -%c %s", comm, c, optarg);
 			break;
+
 		case '1':									/* Pass these switches directly to ssh */
 		case '2':									/* 1 to force version 1, 2 to force version 2 */
 		case '4':									/* -4 for IPv4 */
diff -urN ../nplg/plugins/check_dig.c ./plugins/check_dig.c
--- ../nplg/plugins/check_dig.c	2005-01-28 15:00:58.000000000 +0100
+++ ./plugins/check_dig.c	2005-06-10 15:01:26.000000000 +0200
@@ -14,29 +14,33 @@
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
- $Id: check_dig.c,v 1.40 2005/01/26 21:21:01 tonvoon Exp $
+ $Id: check_dig.c,v 1.3 2005/06/06 11:37:06 exon Exp $
  
 *****************************************************************************/
 
+/* Hackers note:
+ *  There are typecasts to (char *) from _("foo bar") in this file.
+ *  They prevent compiler warnings. Never (ever), permute strings obtained
+ *  that are typecast from (const char *) (which happens when --disable-nls)
+ *  because on some architectures those strings are in non-writable memory */
+
 const char *progname = "check_dig";
-const char *revision = "$Revision: 1.40 $";
+const char *revision = "$Revision: 1.3 $";
 const char *copyright = "2002-2004";
 const char *email = "nagiosplug-devel@lists.sourceforge.net";
 
 #include "common.h"
 #include "netutils.h"
 #include "utils.h"
-#include "popen.h"
+#include "runcmd.h"
 
 int process_arguments (int, char **);
 int validate_arguments (void);
 void print_help (void);
 void print_usage (void);
 
-enum {
-	UNDEFINED = 0,
-	DEFAULT_PORT = 53
-};
+#define UNDEFINED 0
+#define DEFAULT_PORT 53
 
 char *query_address = NULL;
 char *record_type = "A";
@@ -51,16 +55,15 @@
 int
 main (int argc, char **argv)
 {
-	char input_buffer[MAX_INPUT_BUFFER];
 	char *command_line;
-	char *output;
+	output chld_out, chld_err;
+	char *msg = NULL;
+	size_t i;
 	char *t;
 	long microsec;
 	double elapsed_time;
 	int result = STATE_UNKNOWN;
 
-	output = strdup ("");
-
 	setlocale (LC_ALL, "");
 	bindtextdomain (PACKAGE, LOCALEDIR);
 	textdomain (PACKAGE);
@@ -89,100 +92,75 @@
 	}
 
 	/* run the command */
-	child_process = spopen (command_line);
-	if (child_process == NULL) {
-		printf (_("Could not open pipe: %s\n"), command_line);
-		return STATE_UNKNOWN;
+	if((result = np_runcmd(command_line, &chld_out, &chld_err, 0)) != 0) {
+		result = STATE_WARNING;
+		msg = (char *)_("dig returned an error status");
 	}
 
-	child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
-	if (child_stderr == NULL)
-		printf (_("Could not open stderr for %s\n"), command_line);
-
-	while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
-
+	for(i = 0; i < chld_out.lines; i++) {
 		/* the server is responding, we just got the host name... */
-		if (strstr (input_buffer, ";; ANSWER SECTION:")) {
+		if (strstr (chld_out.line[i], ";; ANSWER SECTION:")) {
 
 			/* loop through the whole 'ANSWER SECTION' */
-			do {
+			for(; i < chld_out.lines; i++) {
 				/* get the host address */
-				if (!fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process))
-					break;
-
-				if (strpbrk (input_buffer, "\r\n"))
-					input_buffer[strcspn (input_buffer, "\r\n")] = '\0';
+				if (verbose)
+					printf ("%s\n", chld_out.line[i]);
 
-				if (verbose && !strstr (input_buffer, ";; ")) 
-					printf ("%s\n", input_buffer); 
-
-				if (expected_address==NULL && strstr (input_buffer, query_address) != NULL) {
-					output = strdup(input_buffer);
+				if (strstr (chld_out.line[i], (expected_address == NULL ? query_address : expected_address)) != NULL) {
+					msg = chld_out.line[i];
 					result = STATE_OK;
-				}
-				else if (expected_address != NULL && strstr (input_buffer, expected_address) != NULL) {
-					output = strdup(input_buffer);
-                        	        result = STATE_OK;
-				}
 
-				/* Translate output TAB -> SPACE */
-				t = output;
-				while ((t = index(t, '\t')) != NULL) 
-					*t = ' ';
-
-			} while (!strstr (input_buffer, ";; "));
+					/* Translate output TAB -> SPACE */
+					t = msg;
+					while ((t = strchr(t, '\t')) != NULL) *t = ' ';
+					break;
+				}
+			}
 
 			if (result == STATE_UNKNOWN) {
-		        	asprintf (&output, _("Server not found in ANSWER SECTION"));
-	                        result = STATE_WARNING;
-                        }
-		}
-
-	}
-
-	if (result == STATE_UNKNOWN) {
-		asprintf (&output, _("No ANSWER SECTION found"));
-	}
+				msg = (char *)_("Server not found in ANSWER SECTION");
+				result = STATE_WARNING;
+			}
 
-	while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
-		/* If we get anything on STDERR, at least set warning */
-		result = max_state (result, STATE_WARNING);
-		printf ("%s", input_buffer);
-		if (strlen (output) == 0)
-			output = strdup (1 + index (input_buffer, ':'));
+			/* we found the answer section, so break out of the loop */
+			break;
+		}
 	}
 
-	(void) fclose (child_stderr);
+	if (result == STATE_UNKNOWN)
+		msg = (char *)_("No ANSWER SECTION found");
 
-	/* close the pipe */
-	if (spclose (child_process)) {
-		result = max_state (result, STATE_WARNING);
-		if (strlen (output) == 0)
-			asprintf (&output, _("dig returned an error status"));
+	/* If we get anything on STDERR, at least set warning */
+	if(chld_err.buflen > 0) {
+		result = max_state(result, STATE_WARNING);
+		if(!msg) for(i = 0; i < chld_err.lines; i++) {
+			msg = strchr(chld_err.line[0], ':');
+			if(msg) {
+				msg++;
+				break;
+			}
+		}
 	}
 
 	microsec = deltime (tv);
 	elapsed_time = (double)microsec / 1.0e6;
 
-	if (output == NULL || strlen (output) == 0)
-		asprintf (&output, _(" Probably a non-existent host/domain"));
-
 	if (critical_interval > UNDEFINED && elapsed_time > critical_interval)
 		result = STATE_CRITICAL;
 
 	else if (warning_interval > UNDEFINED && elapsed_time > warning_interval)
 		result = STATE_WARNING;
 
-	asprintf (&output, _("%.3f seconds response time (%s)"), elapsed_time, output);
-
-	printf ("DNS %s - %s|%s\n",
-	        state_text (result), output,
+	printf ("DNS %s - %.3f seconds response time (%s)|%s\n",
+	        state_text (result), elapsed_time,
+	        msg ? msg : _("Probably a non-existent host/domain"),
 	        fperfdata("time", elapsed_time, "s",
-	                 (warning_interval>UNDEFINED?TRUE:FALSE),
-	                 warning_interval,
-	                 (critical_interval>UNDEFINED?TRUE:FALSE),
-	                 critical_interval,
-									 TRUE, 0, FALSE, 0));
+	                  (warning_interval>UNDEFINED?TRUE:FALSE),
+	                  warning_interval,
+	                  (critical_interval>UNDEFINED?TRUE:FALSE),
+					  critical_interval,
+					  TRUE, 0, FALSE, 0));
 	return result;
 }
 
@@ -359,6 +337,6 @@
 {
 	printf ("\
 Usage: %s -H host -l lookup [-p <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@lists.sourceforge.net";
 
 #include "common.h"
-#include "popen.h"
 #include "utils.h"
 #include "netutils.h"
+#include "runcmd.h"
 
 int process_arguments (int, char **);
 int validate_arguments (void);
@@ -51,8 +51,8 @@
 {
 	char *command_line = NULL;
 	char input_buffer[MAX_INPUT_BUFFER];
-	char *output = NULL;
 	char *address = NULL;
+	char *msg = NULL;
 	char *temp_buffer = NULL;
 	int non_authoritative = FALSE;
 	int result = STATE_UNKNOWN;
@@ -61,6 +61,8 @@
 	struct timeval tv;
 	int multi_address;
 	int parse_address = FALSE; /* This flag scans for Address: but only after Name: */
+	output chld_out, chld_err;
+	size_t i;
 
 	setlocale (LC_ALL, "");
 	bindtextdomain (PACKAGE, LOCALEDIR);
@@ -85,37 +87,31 @@
 		printf ("%s\n", command_line);
 
 	/* run the command */
-	child_process = spopen (command_line);
-	if (child_process == NULL) {
-		printf (_("Could not open pipe: %s\n"), command_line);
-		return STATE_UNKNOWN;
+	if((np_runcmd(command_line, &chld_out, &chld_err, 0)) != 0) {
+		msg = (char *)_("nslookup returned error status");
+		result = STATE_WARNING;
 	}
 
-	child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
-	if (child_stderr == NULL)
-		printf (_("Could not open stderr for %s\n"), command_line);
-
 	/* scan stdout */
-	while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
-
+	for(i = 0; i < chld_out.lines; i++) {
 		if (verbose)
-			printf ("%s", input_buffer);
+			printf ("%s", chld_out.line[i]);
 
-		if (strstr (input_buffer, ".in-addr.arpa")) {
-			if ((temp_buffer = strstr (input_buffer, "name = ")))
+		if (strstr (chld_out.line[i], ".in-addr.arpa")) {
+			if ((temp_buffer = strstr (chld_out.line[i], "name = ")))
 				address = strdup (temp_buffer + 7);
 			else {
-				output = strdup (_("Warning plugin error"));
+				msg = (char *)_("Warning plugin error");
 				result = STATE_WARNING;
 			}
 		}
 
 		/* the server is responding, we just got the host name... */
-		if (strstr (input_buffer, "Name:"))
+		if (strstr (chld_out.line[i], "Name:"))
 			parse_address = TRUE;
-		else if (parse_address == TRUE && (strstr (input_buffer, "Address:") ||
-		         strstr (input_buffer, "Addresses:"))) {
-			temp_buffer = index (input_buffer, ':');
+		else if (parse_address == TRUE && (strstr (chld_out.line[i], "Address:") ||
+		         strstr (chld_out.line[i], "Addresses:"))) {
+			temp_buffer = index (chld_out.line[i], ':');
 			temp_buffer++;
 
 			/* Strip leading spaces */
@@ -135,59 +131,47 @@
 				asprintf(&address, "%s,%s", address, temp_buffer);
 		}
 
-		else if (strstr (input_buffer, _("Non-authoritative answer:"))) {
+		else if (strstr (chld_out.line[i], _("Non-authoritative answer:"))) {
 			non_authoritative = TRUE;
 		}
 
-		result = error_scan (input_buffer);
+		result = error_scan (chld_out.line[i]);
 		if (result != STATE_OK) {
-			output = strdup (1 + index (input_buffer, ':'));
-			strip (output);
+			msg = strchr (chld_out.line[i], ':');
+			if(msg) msg++;
 			break;
 		}
-
 	}
 
 	/* scan stderr */
-	while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
-
+	for(i = 0; i < chld_err.lines; i++) {
 		if (verbose)
-			printf ("%s", input_buffer);
+			printf ("%s", chld_err.line[i]);
 
-		if (error_scan (input_buffer) != STATE_OK) {
-			result = max_state (result, error_scan (input_buffer));
-			output = strdup (1 + index (input_buffer, ':'));
-			strip (output);
+		if (error_scan (chld_err.line[i]) != STATE_OK) {
+			result = max_state (result, error_scan (chld_err.line[i]));
+			msg = strchr(input_buffer, ':');
+			if(msg) msg++;
 		}
 	}
 
-	/* close stderr */
-	(void) fclose (child_stderr);
-
-	/* close stdout */
-	if (spclose (child_process)) {
-		result = max_state (result, STATE_WARNING);
-		if (output == NULL || !strcmp (output, ""))
-			output = strdup (_("nslookup returned error status"));
-	}
-
-	/* If we got here, we should have an address string, 
-		 and we can segfault if we do not */
+	/* If we got here, we should have an address string,
+	 * and we can segfault if we do not */
 	if (address==NULL || strlen(address)==0)
 		die (STATE_CRITICAL,
-		     _("DNS CRITICAL - '%s' output parsing exited with no address\n"),
+		     _("DNS CRITICAL - '%s' msg parsing exited with no address\n"),
 		     NSLOOKUP_COMMAND);
 
 	/* compare to expected address */
 	if (result == STATE_OK && match_expected_address && strcmp(address, expected_address)) {
 		result = STATE_CRITICAL;
-		asprintf(&output, _("expected %s but got %s"), expected_address, address);
+		asprintf(&msg, _("expected %s but got %s"), expected_address, address);
 	}
 
 	/* check if authoritative */
 	if (result == STATE_OK && expect_authority && non_authoritative) {
 		result = STATE_CRITICAL;
-		asprintf(&output, _("server %s is not authoritative for %s"), dns_server, query_address);
+		asprintf(&msg, _("server %s is not authoritative for %s"), dns_server, query_address);
 	}
 
 	microsec = deltime (tv);
@@ -206,13 +190,13 @@
 	}
 	else if (result == STATE_WARNING)
 		printf (_("DNS WARNING - %s\n"),
-		        !strcmp (output, "") ? _(" Probably a non-existent host/domain") : output);
+		        !strcmp (msg, "") ? _(" Probably a non-existent host/domain") : msg);
 	else if (result == STATE_CRITICAL)
 		printf (_("DNS CRITICAL - %s\n"),
-		        !strcmp (output, "") ? _(" Probably a non-existent host/domain") : output);
+		        !strcmp (msg, "") ? _(" Probably a non-existent host/domain") : msg);
 	else
 		printf (_("DNS UNKNOW - %s\n"),
-		        !strcmp (output, "") ? _(" Probably a non-existent host/domain") : output);
+		        !strcmp (msg, "") ? _(" Probably a non-existent host/domain") : msg);
 
 	return result;
 }
diff -urN ../nplg/plugins/check_fping.c ./plugins/check_fping.c
--- ../nplg/plugins/check_fping.c	2005-01-05 21:53:13.000000000 +0100
+++ ./plugins/check_fping.c	2005-06-10 15:01:26.000000000 +0200
@@ -14,26 +14,24 @@
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
- $Id: check_fping.c,v 1.24 2004/12/25 23:17:44 opensides Exp $
+ $Id: check_fping.c,v 1.2 2005/06/05 21:55:26 exon Exp $
  
 ******************************************************************************/
 
 const char *progname = "check_fping";
-const char *revision = "$Revision: 1.24 $";
+const char *revision = "$Revision: 1.2 $";
 const char *copyright = "2000-2004";
 const char *email = "nagiosplug-devel@lists.sourceforge.net";
 
 #include "common.h"
-#include "popen.h"
 #include "netutils.h"
 #include "utils.h"
+#include "runcmd.h"
 
-enum {
-	PACKET_COUNT = 1,
-	PACKET_SIZE = 56,
-	PL = 0,
-	RTA = 1
-};
+#define	PACKET_COUNT 1
+#define PACKET_SIZE 56
+#define PL 0
+#define RTA 1
 
 int textscan (char *buf);
 int process_arguments (int, char **);
@@ -59,11 +57,11 @@
 {
 /* normaly should be 	int result = STATE_UNKNOWN; */
 
-	int status = STATE_UNKNOWN;
+	int result = STATE_UNKNOWN;
 	char *server = NULL;
 	char *command_line = NULL;
-	char *input_buffer = NULL;
-	input_buffer = malloc (MAX_INPUT_BUFFER);
+	output chld_out, chld_err;
+	size_t i;
 
 	setlocale (LC_ALL, "");
 	bindtextdomain (PACKAGE, LOCALEDIR);
@@ -79,43 +77,21 @@
 	          packet_size, packet_count, server);
 
 	if (verbose)
-		printf ("%s\n", command_line);
+		printf ("command_line: %s\n", command_line);
 
 	/* run the command */
-	child_process = spopen (command_line);
-	if (child_process == NULL) {
-		printf (_("Could not open pipe: %s\n"), command_line);
-		return STATE_UNKNOWN;
-	}
-
-	child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
-	if (child_stderr == NULL) {
-		printf (_("Could not open stderr for %s\n"), command_line);
-	}
+	if((np_runcmd(command_line, &chld_out, &chld_err, 0)) || chld_err.buflen)
+		result = STATE_WARNING;
 
-	while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
-		if (verbose)
-			printf ("%s", input_buffer);
-		status = max_state (status, textscan (input_buffer));
-	}
-
-	/* If we get anything on STDERR, at least set warning */
-	while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
-		status = max_state (status, STATE_WARNING);
-		if (verbose)
-			printf ("%s", input_buffer);
-		status = max_state (status, textscan (input_buffer));
-	}
-	(void) fclose (child_stderr);
+	for(i = 0; i < chld_out.lines; i++)
+		result = max_state (result, textscan (chld_out.line[i]));
 
-	/* close the pipe */
-	if (spclose (child_process))
-		/* need to use max_state not max */
-		status = max_state (status, STATE_WARNING);
+	printf ("FPING %s - %s\n", state_text (result), server_name);
 
-	printf ("FPING %s - %s\n", state_text (status), server_name);
+	if (verbose) for(i = 0; i < chld_out.lines; i++)
+			printf ("%s", chld_out.line[i]);
 
-	return status;
+	return result;
 }
 
 
@@ -127,7 +103,7 @@
 	char *losstr = NULL;
 	double loss;
 	double rta;
-	int status = STATE_UNKNOWN;
+	int result = STATE_UNKNOWN;
 
 	if (strstr (buf, "not found")) {
 		die (STATE_CRITICAL, _("FPING UNKNOW - %s not found\n"), server_name);
@@ -143,7 +119,7 @@
 
 	}
 	else if (strstr (buf, "is alive")) {
-		status = STATE_OK;
+		result = STATE_OK;
 
 	}
 	else if (strstr (buf, "xmt/rcv/%loss") && strstr (buf, "min/avg/max")) {
@@ -156,18 +132,18 @@
 		loss = strtod (losstr, NULL);
 		rta = strtod (rtastr, NULL);
 		if (cpl_p == TRUE && loss > cpl)
-			status = STATE_CRITICAL;
+			result = STATE_CRITICAL;
 		else if (crta_p == TRUE  && rta > crta)
-			status = STATE_CRITICAL;
+			result = STATE_CRITICAL;
 		else if (wpl_p == TRUE && loss > wpl)
-			status = STATE_WARNING;
+			result = STATE_WARNING;
 		else if (wrta_p == TRUE && rta > wrta)
-			status = STATE_WARNING;
+			result = STATE_WARNING;
 		else
-			status = STATE_OK;
-		die (status,
+			result = STATE_OK;
+		die (result,
 		      _("FPING %s - %s (loss=%.0f%%, rta=%f ms)|%s %s\n"),
-				 state_text (status), server_name, loss, rta,
+				 state_text (result), server_name, loss, rta,
 		     perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, TRUE, 0, TRUE, 100),
 		     fperfdata ("rta", rta/1.0e3, "s", wrta_p, wrta/1.0e3, crta_p, crta/1.0e3, TRUE, 0, FALSE, 0));
 
@@ -179,24 +155,24 @@
 		losstr = 1 + strstr (losstr, "/");
 		loss = strtod (losstr, NULL);
 		if (atoi(losstr) == 100)
-			status = STATE_CRITICAL;
+			result = STATE_CRITICAL;
 		else if (cpl_p == TRUE && loss > cpl)
-			status = STATE_CRITICAL;
+			result = STATE_CRITICAL;
 		else if (wpl_p == TRUE && loss > wpl)
-			status = STATE_WARNING;
+			result = STATE_WARNING;
 		else
-			status = STATE_OK;
+			result = STATE_OK;
 		/* loss=%.0f%%;%d;%d;0;100 */
-		die (status, _("FPING %s - %s (loss=%.0f%% )|%s\n"),
-		     state_text (status), server_name, loss ,
+		die (result, _("FPING %s - %s (loss=%.0f%% )|%s\n"),
+		     state_text (result), server_name, loss ,
 		     perfdata ("loss", (long int)loss, "%", wpl_p, wpl, cpl_p, cpl, TRUE, 0, TRUE, 100));
 	
 	}
 	else {
-		status = max_state (status, STATE_WARNING);
+		result = max_state (result, STATE_WARNING);
 	}
 
-	return status;
+	return result;
 }
 
 
diff -urN ../nplg/plugins/check_game.c ./plugins/check_game.c
--- ../nplg/plugins/check_game.c	2005-01-05 21:53:13.000000000 +0100
+++ ./plugins/check_game.c	2005-06-10 15:01:26.000000000 +0200
@@ -14,17 +14,17 @@
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
-* $Id: check_game.c,v 1.22 2004/12/25 23:17:44 opensides Exp $
+* $Id: check_game.c,v 1.2 2005/06/05 21:55:26 exon Exp $
 *****************************************************************************/
 
 const char *progname = "check_game";
-const char *revision = "$Revision: 1.22 $";
+const char *revision = "$Revision: 1.2 $";
 const char *copyright = "2002-2004";
 const char *email = "nagiosplug-devel@lists.sourceforge.net";
 
 #include "common.h"
-#include "popen.h"
 #include "utils.h"
+#include "runcmd.h"
 
 int process_arguments (int, char **);
 int validate_arguments (void);
@@ -57,9 +57,9 @@
 	char *command_line;
 	int result = STATE_UNKNOWN;
 	FILE *fp;
-	char input_buffer[MAX_INPUT_BUFFER];
 	char *p, *ret[QSTAT_MAX_RETURN_ARGS];
-	int i;
+	size_t i = 0;
+	output chld_out;
 
 	setlocale (LC_ALL, "");
 	bindtextdomain (PACKAGE, LOCALEDIR);
@@ -80,17 +80,9 @@
 	if (verbose > 0)
 		printf ("%s\n", command_line);
 
-	/* run the command */
-	fp = spopen (command_line);
-	if (fp == NULL) {
-		printf (_("Could not open pipe: %s\n"), command_line);
-		return STATE_UNKNOWN;
-	}
-
-	fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp);	/* Only interested in the first line */
-
-	/* strip the newline character from the end of the input */
-	input_buffer[strlen (input_buffer) - 1] = 0;
+	/* run the command. historically, this plugin ignores output on stderr,
+	 * as well as return status of the qstat program */
+	(void)np_runcmd(command_line, &chld_out, NULL, 0);
 
 	/* sanity check */
 	/* was thinking about running qstat without any options, capturing the
@@ -102,18 +94,13 @@
 	   In the end, I figured I'd simply let an error occur & then trap it
 	 */
 
-	if (!strncmp (input_buffer, "unknown option", 14)) {
+	if (!strncmp (chld_out.line[0], "unknown option", 14)) {
 		printf (_("CRITICAL - Host type parameter incorrect!\n"));
 		result = STATE_CRITICAL;
 		return result;
 	}
 
-	/* initialize the returned data buffer */
-	for (i = 0; i < QSTAT_MAX_RETURN_ARGS; i++)
-		ret[i] = strdup("");
-
-	i = 0;
-	p = (char *) strtok (input_buffer, QSTAT_DATA_DELIMITER);
+	p = (char *) strtok (chld_out.line[0], QSTAT_DATA_DELIMITER);
 	while (p != NULL) {
 		ret[i] = p;
 		p = (char *) strtok (NULL, QSTAT_DATA_DELIMITER);
@@ -141,17 +128,14 @@
 		        ret[qstat_game_field], 
 		        ret[qstat_map_field],
 		        ret[qstat_ping_field],
-						perfdata ("players", atol(ret[qstat_game_players]), "",
+		        perfdata ("players", atol(ret[qstat_game_players]), "",
 		                  FALSE, 0, FALSE, 0,
 		                  TRUE, 0, TRUE, atol(ret[qstat_game_players_max])),
-						fperfdata ("ping", strtod(ret[qstat_ping_field], NULL), "",
+		        fperfdata ("ping", strtod(ret[qstat_ping_field], NULL), "",
 		                  FALSE, 0, FALSE, 0,
 		                  TRUE, 0, FALSE, 0));
 	}
 
-	/* close the pipe */
-	spclose (fp);
-
 	return result;
 }
 
diff -urN ../nplg/plugins/check_hpjd.c ./plugins/check_hpjd.c
--- ../nplg/plugins/check_hpjd.c	2005-01-05 21:53:13.000000000 +0100
+++ ./plugins/check_hpjd.c	2005-06-10 15:01:26.000000000 +0200
@@ -14,24 +14,22 @@
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
-* $Id: check_hpjd.c,v 1.31 2004/12/25 23:17:44 opensides Exp $
+* $Id: check_hpjd.c,v 1.4 2005/06/06 11:37:06 exon Exp $
 *****************************************************************************/
 
 const char *progname = "check_hpjd";
-const char *revision = "$Revision: 1.31 $";
+const char *revision = "$Revision: 1.4 $";
 const char *copyright = "2000-2004";
 const char *email = "nagiosplug-devel@lists.sourceforge.net";
 
 #include "common.h"
-#include "popen.h"
 #include "utils.h"
 #include "netutils.h"
+#include "runcmd.h"
 
 #define DEFAULT_COMMUNITY "public"
 
-
-const char *option_summary = "-H host [-C community]\n";
-
+/* this macro is only avavilable from main() */
 #define HPJD_LINE_STATUS           ".1.3.6.1.4.1.11.2.3.9.1.1.2.1"
 #define HPJD_PAPER_STATUS          ".1.3.6.1.4.1.11.2.3.9.1.1.2.2"
 #define HPJD_INTERVENTION_REQUIRED ".1.3.6.1.4.1.11.2.3.9.1.1.2.3"
@@ -44,42 +42,50 @@
 #define HPJD_GD_DOOR_OPEN          ".1.3.6.1.4.1.11.2.3.9.1.1.2.17"
 #define HPJD_GD_PAPER_OUTPUT       ".1.3.6.1.4.1.11.2.3.9.1.1.2.19"
 #define HPJD_GD_STATUS_DISPLAY     ".1.3.6.1.4.1.11.2.3.9.1.1.3"
+#define SNMP_VARS 12
 
 #define ONLINE		0
 #define OFFLINE		1
 
-int process_arguments (int, char **);
-int validate_arguments (void);
-void print_help (void);
+/* make it compile without warnings when internationalization is disabled */
+#ifndef ENABLE_NLS
+# ifdef _
+#  undef _
+# endif
+# define _(x) x
+#endif
+
+static int process_arguments (int, char **);
+static int validate_arguments (void);
+static void print_help (void);
 void print_usage (void);
 
-char *community = NULL;
-char *address = NULL;
+static char *community = NULL;
+static char *address = NULL;
+
 
 int
 main (int argc, char **argv)
 {
 	char command_line[1024];
-	int result = STATE_UNKNOWN;
-	int line;
-	char input_buffer[MAX_INPUT_BUFFER];
-	char query_string[512];
-	char *errmsg;
-	char *temp_buffer;
-	int line_status = ONLINE;
-	int paper_status = 0;
-	int intervention_required = 0;
-	int peripheral_error = 0;
-	int paper_jam = 0;
-	int paper_out = 0;
-	int toner_low = 0;
-	int page_punt = 0;
-	int memory_out = 0;
-	int door_open = 0;
-	int paper_output = 0;
-	char display_message[MAX_INPUT_BUFFER];
-
-	errmsg = malloc(MAX_INPUT_BUFFER);
+	int result = STATE_OK;
+	size_t i, val = 0;
+	int errorflag = 0;	/* bitflag error tracker */
+	output chld_out, chld_err;
+	char *errmsg_strings[11];
+
+	/* populate the the error message array */
+	errmsg_strings[0] = _("Printer Offline");
+	errmsg_strings[1] = _("Unknown Paper Error");
+	errmsg_strings[2] = _("Intervention Required");
+	errmsg_strings[3] = _("Peripheral Error");
+	errmsg_strings[4] = _("Paper Jam");
+	errmsg_strings[5] = _("Out of Paper");
+	errmsg_strings[6] = _("Toner Low");
+	errmsg_strings[7] = _("Data too Slow for Engine");
+	errmsg_strings[8] = _("Insufficient Memory");
+	errmsg_strings[9] = _("A Door is Open");
+	errmsg_strings[10] = _("Output Tray is Full");
 
 	setlocale (LC_ALL, "");
 	bindtextdomain (PACKAGE, LOCALEDIR);
@@ -88,206 +94,99 @@
 	if (process_arguments (argc, argv) == ERROR)
 		usage4 (_("Could not parse arguments"));
 
-	/* removed ' 2>1' at end of command 10/27/1999 - EG */
-	/* create the query string */
-	sprintf
-		(query_string,
-		 "%s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0",
-		 HPJD_LINE_STATUS,
-		 HPJD_PAPER_STATUS,
-		 HPJD_INTERVENTION_REQUIRED,
-		 HPJD_GD_PERIPHERAL_ERROR,
-		 HPJD_GD_PAPER_JAM,
-		 HPJD_GD_PAPER_OUT,
-		 HPJD_GD_TONER_LOW,
-		 HPJD_GD_PAGE_PUNT,
-		 HPJD_GD_MEMORY_OUT,
-		 HPJD_GD_DOOR_OPEN, HPJD_GD_PAPER_OUTPUT, HPJD_GD_STATUS_DISPLAY);
-
-	/* get the command to run */
-	sprintf (command_line, "%s -OQa -m : -v 1 -c %s %s %s", PATH_TO_SNMPGET, community, 
-									address, query_string);
+	/* create the command-line. Get status display line first, so we can
+	 * match line status against powersave as we parse it */
+	sprintf (command_line, "%s -Oqv -m : -v 1 -c %s %s "
+	         "%s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0 %s.0",
+	         PATH_TO_SNMPGET, community, address,
+	         HPJD_GD_STATUS_DISPLAY,
+	         HPJD_LINE_STATUS,
+	         HPJD_PAPER_STATUS,
+	         HPJD_INTERVENTION_REQUIRED,
+	         HPJD_GD_PERIPHERAL_ERROR,
+	         HPJD_GD_PAPER_JAM,
+	         HPJD_GD_PAPER_OUT,
+	         HPJD_GD_TONER_LOW,
+	         HPJD_GD_PAGE_PUNT,
+	         HPJD_GD_MEMORY_OUT,
+	         HPJD_GD_DOOR_OPEN,
+	         HPJD_GD_PAPER_OUTPUT);
 
 	/* run the command */
-	child_process = spopen (command_line);
-	if (child_process == NULL) {
-		printf (_("Could not open pipe: %s\n"), command_line);
-		return STATE_UNKNOWN;
-	}
-
-	child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
-	if (child_stderr == NULL) {
-		printf (_("Could not open stderr for %s\n"), command_line);
-	}
-
-	result = STATE_OK;
-
-	line = 0;
-	while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
+	if((np_runcmd(command_line, &chld_out, &chld_err, 0)) || chld_err.buflen)
+		result = STATE_WARNING;
 
-		/* strip the newline character from the end of the input */
-		if (input_buffer[strlen (input_buffer) - 1] == '\n')
-			input_buffer[strlen (input_buffer) - 1] = 0;
-
-		line++;
-
-		temp_buffer = strtok (input_buffer, "=");
-		temp_buffer = strtok (NULL, "=");
-
-		if (temp_buffer == NULL) {
-
-				result = STATE_UNKNOWN;
-				strcpy (errmsg, input_buffer);
-
-		} else {
-
-			switch (line) {
-
-			case 1:										/* 1st line should contain the line status */
-				line_status = atoi (temp_buffer);
-				break;
-			case 2:										/* 2nd line should contain the paper status */
-				paper_status = atoi (temp_buffer);
-				break;
-			case 3:										/* 3rd line should be intervention required */
-				intervention_required = atoi (temp_buffer);
-				break;
-			case 4:										/* 4th line should be peripheral error */
-				peripheral_error = atoi (temp_buffer);
-				break;
-			case 5:										/* 5th line should contain the paper jam status */
-				paper_jam = atoi (temp_buffer);
-				break;
-			case 6:										/* 6th line should contain the paper out status */
-				paper_out = atoi (temp_buffer);
-				break;
-			case 7:										/* 7th line should contain the toner low status */
-				toner_low = atoi (temp_buffer);
-				break;
-			case 8:										/* did data come too slow for engine */
-				page_punt = atoi (temp_buffer);
-				break;
-			case 9:										/* did we run out of memory */
-				memory_out = atoi (temp_buffer);
-				break;
-			case 10:										/* is there a door open */
-				door_open = atoi (temp_buffer);
-				break;
-			case 11:										/* is output tray full */
-				paper_output = atoi (temp_buffer);
-				break;
-			case 12:										/* display panel message */
-				strcpy (display_message, temp_buffer + 1);
-				break;
-			default:
-				break;
-			}
-
-		}
-
-		/* break out of the read loop if we encounter an error */
-		if (result != STATE_OK)
-			break;
-	}
+	/* if there was none or not enough output, display an error and exit */
+	if (chld_out.buflen == 0 || chld_out.lines != SNMP_VARS - 1) {
+		if(chld_err.buflen) printf("%s : ", chld_err.line[0]);
 
-	/* WARNING if output found on stderr */
-	if (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
-		result = max_state (result, STATE_WARNING);
-		/* remove CRLF */
-		if (input_buffer[strlen (input_buffer) - 1] == '\n')
-			input_buffer[strlen (input_buffer) - 1] = 0;
-		sprintf (errmsg, "%s", input_buffer );
+		if(chld_out.buflen == 0)
+			printf (_("No data returned from %s\n"), address );
+		else
+			printf(_("Not enough data returned from %s\n"), address);
 
-	}
-	
-	/* close stderr */
-	(void) fclose (child_stderr);
-
-	/* close the pipe */
-	if (spclose (child_process))
-		result = max_state (result, STATE_WARNING);
-
-	/* if there wasn't any output, display an error */
-	if (line == 0) {
-
-		/* might not be the problem, but most likely is. */
-		result = STATE_UNKNOWN ;
-		asprintf (&errmsg, "%s : Timeout from host %s\n", errmsg, address );
-		 
+		return STATE_UNKNOWN;
 	}
 
-	/* if we had no read errors, check the printer status results... */
-	if (result == STATE_OK) {
+	for(i = 1; i < chld_out.lines; i++) {
+		/* move to next if there's no error tag */
+		if(!(val = (size_t)strtol(chld_out.line[i], NULL, 0)))
+			continue;
+
+		/* tag the error */
+		errorflag |= 1 << i;
+
+		/* this switch statement is only for additional exception handling */
+		switch (i) {
+		case 1:		/* line status */
+			/* clear this flag if it's powersaving (we know it's set if
+			 * we get here, so use xor and save 2 instructions) */
+			if(!strstr(chld_out.line[0], "POWERSAVE ON"))
+				errorflag ^= 1 << i;
+			break;
 
-		if (paper_jam) {
-			result = STATE_WARNING;
-			strcpy (errmsg, _("Paper Jam"));
-		}
-		else if (paper_out) {
-			result = STATE_WARNING;
-			strcpy (errmsg, _("Out of Paper"));
-		}
-		else if (line_status == OFFLINE) {
-			if (strcmp (errmsg, "POWERSAVE ON") != 0) {
-				result = STATE_WARNING;
-				strcpy (errmsg, _("Printer Offline"));
-			}
-		}
-		else if (peripheral_error) {
-			result = STATE_WARNING;
-			strcpy (errmsg, _("Peripheral Error"));
-		}
-		else if (intervention_required) {
-			result = STATE_WARNING;
-			strcpy (errmsg, _("Intervention Required"));
-		}
-		else if (toner_low) {
-			result = STATE_WARNING;
-			strcpy (errmsg, _("Toner Low"));
-		}
-		else if (memory_out) {
-			result = STATE_WARNING;
-			strcpy (errmsg, _("Insufficient Memory"));
-		}
-		else if (door_open) {
-			result = STATE_WARNING;
-			strcpy (errmsg, _("A Door is Open"));
-		}
-		else if (paper_output) {
-			result = STATE_WARNING;
-			strcpy (errmsg, _("Output Tray is Full"));
-		}
-		else if (page_punt) {
-			result = STATE_WARNING;
-			strcpy (errmsg, _("Data too Slow for Engine"));
-		}
-		else if (paper_status) {
-			result = STATE_WARNING;
-			strcpy (errmsg, _("Unknown Paper Error"));
+		case 2:		/* paper status */
+		case 3:		/* intervention required */
+		case 4:		/* peripheral error */
+		case 5:		/* paper jam */
+		case 6:		/* paper out */
+		case 7:		/* toner low */
+		case 8:		/* data came too slow for engine */
+		case 9:		/* out of memory */
+		case 10:	/* door open */
+		case 11:	/* output tray full */
+			break;
 		}
 	}
 
-	if (result == STATE_OK)
-		printf (_("Printer ok - (%s)\n"), display_message);
-
-	else if (result == STATE_UNKNOWN) {
+	/* if some error occurred, print a starting line and all the errors */
+	if(errorflag) {
+		printf ("%s (%s)", chld_err.buflen != 0 ? chld_err.buf : "",
+		        chld_out.line[0]);
 
-		printf ("%s\n", errmsg);
+		for(i = 0; i < SNMP_VARS; i++) { /* loop the error flags */
+			if((errorflag >> i) & 1) /* only print if flag is set */
+				printf(" :: %s", errmsg_strings[i++]);
+		}
 
-		/* if printer could not be reached, escalate to critical */
-		if (strstr (errmsg, "Timeout"))
-			result = STATE_CRITICAL;
+		return STATE_CRITICAL;
 	}
 
-	else if (result == STATE_WARNING)
-		printf ("%s (%s)\n", errmsg, display_message);
+	/* set WARNING if output on stderr */
+	if (chld_err.buflen) {
+		printf("WARNING - Printer seems ok, but %s printed to stderr (%s)",
+		       PATH_TO_SNMPGET, chld_err.line[0]);
+		return STATE_WARNING;
+	}
 
-	return result;
+	/* all is well if we end up here */
+	printf (_("Printer ok - (%s)\n"), chld_out.line[0]);
+	return STATE_OK;
 }
 
 
 /* process command-line arguments */
-int
+static int
 process_arguments (int argc, char **argv)
 {
 	int c;
@@ -296,9 +195,6 @@
 	static struct option longopts[] = {
 		{"hostname", required_argument, 0, 'H'},
 		{"community", required_argument, 0, 'C'},
-/*  		{"critical",       required_argument,0,'c'}, */
-/*  		{"warning",        required_argument,0,'w'}, */
-/*  		{"port",           required_argument,0,'P'}, */
 		{"version", no_argument, 0, 'V'},
 		{"help", no_argument, 0, 'h'},
 		{0, 0, 0, 0}
@@ -307,7 +203,6 @@
 	if (argc < 2)
 		return ERROR;
 
-	
 	while (1) {
 		c = getopt_long (argc, argv, "+hVH:C:", longopts, &option);
 
@@ -317,7 +212,7 @@
 		switch (c) {
 		case 'H':									/* hostname */
 			if (is_host (optarg)) {
-				address = strscpy(address, optarg) ;
+				address = strdup(optarg) ;
 			}
 			else {
 				usage2 (_("Invalid hostname/address"), optarg);
@@ -346,26 +241,26 @@
 			usage2 (_("Invalid hostname/address"), argv[c]);
 		}
 	}
-	
+
 	if (community == NULL) {
 		if (argv[c] != NULL )
 			community = argv[c];
 		else
-			community = strdup (DEFAULT_COMMUNITY);
+			community = DEFAULT_COMMUNITY;
 	}
 
 	return validate_arguments ();
 }
 
 
-int
+static int
 validate_arguments (void)
 {
 	return OK;
 }
 
 
-void
+static void
 print_help (void)
 {
 	print_revision (progname, revision);
@@ -389,7 +284,6 @@
 }
 
 
-
 void
 print_usage (void)
 {
diff -urN ../nplg/plugins/check_load.c ./plugins/check_load.c
--- ../nplg/plugins/check_load.c	2005-05-30 17:44:13.000000000 +0200
+++ ./plugins/check_load.c	2005-06-10 15:01:26.000000000 +0200
@@ -14,18 +14,18 @@
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  
- $Id: check_load.c,v 1.28 2005/05/28 01:21:54 seanius Exp $
+ $Id: check_load.c,v 1.3 2005/06/05 21:55:26 exon Exp $
 
 ******************************************************************************/
 
 const char *progname = "check_load";
-const char *revision = "$Revision: 1.28 $";
+const char *revision = "$Revision: 1.3 $";
 const char *copyright = "1999-2004";
 const char *email = "nagiosplug-devel@lists.sourceforge.net";
 
 #include "common.h"
 #include "utils.h"
-#include "popen.h"
+#include "runcmd.h"
 
 #ifdef HAVE_SYS_LOADAVG_H
 #include <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@lists.sourceforge.net";
 
 #include "common.h"
-#include "popen.h"
+#include "runcmd.h"
 #include "utils.h"
 
 int process_arguments (int, char **);
@@ -55,6 +55,8 @@
 	int procrss = 0;
 	float procpcpu = 0;
 	char procstat[8];
+	/* procetime is unused in most configurations, but may be in PS_VAR_LIST
+	 * so it must be here in spite of it producing compiler warnings */
 	char procetime[MAX_INPUT_BUFFER];
 	char procprog[MAX_INPUT_BUFFER];
 	char *procargs;
@@ -62,6 +64,8 @@
 	int expected_cols = PS_COLS - 1;
 	const char *zombie = "Z";
 	char *temp_string;
+	output chld_out, chld_err;
+	size_t i;
 
 	setlocale (LC_ALL, "");
 	bindtextdomain (PACKAGE, LOCALEDIR);
@@ -99,40 +103,30 @@
 		printf(_("command: %s\n"), PS_COMMAND);
 
 	/* run the command to check for the Nagios process.. */
-	child_process = spopen (PS_COMMAND);
-	if (child_process == NULL) {
-		printf (_("Could not open pipe: %s\n"), PS_COMMAND);
-		return STATE_UNKNOWN;
-	}
-
-	child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
-	if (child_stderr == NULL) {
-		printf (_("Could not open stderr for %s\n"), PS_COMMAND);
-	}
-
-	fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
+	if((result = np_runcmd(PS_COMMAND, &chld_out, &chld_err, 0)) != 0)
+		result = STATE_WARNING;
 
 	/* count the number of matching Nagios processes... */
-	while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
-		cols = sscanf (input_buffer, PS_FORMAT, PS_VARLIST);
-                /* Zombie processes do not give a procprog command */
-                if ( cols == (expected_cols - 1) && strstr(procstat, zombie) ) {
-                        cols = expected_cols;
-                        /* Set some value for procargs for the strip command further below
-                        Seen to be a problem on some Solaris 7 and 8 systems */
-                        input_buffer[pos] = '\n';
-                        input_buffer[pos+1] = 0x0;
-                }
+	for(i = 0; i < chld_out.lines; i++) {
+		cols = sscanf (chld_out.line[i], PS_FORMAT, PS_VARLIST);
+		/* Zombie processes do not give a procprog command */
+		if ( cols == (expected_cols - 1) && strstr(procstat, zombie) ) {
+			cols = expected_cols;
+			/* Set some value for procargs for the strip command further below
+			 * Seen to be a problem on some Solaris 7 and 8 systems */
+			chld_out.line[i][pos] = '\n';
+			chld_out.line[i][pos+1] = 0x0;
+		}
 		if ( cols >= expected_cols ) {
-			asprintf (&procargs, "%s", input_buffer + pos);
+			asprintf (&procargs, "%s", chld_out.line[i] + pos);
 			strip (procargs);
-			
+
 			/* Some ps return full pathname for command. This removes path */
-                        temp_string = strtok ((char *)procprog, "/");
-                        while (temp_string) {
-                                strcpy(procprog, temp_string);
-                                temp_string = strtok (NULL, "/");
-                        }
+			temp_string = strtok ((char *)procprog, "/");
+			while (temp_string) {
+				strcpy(procprog, temp_string);
+				temp_string = strtok (NULL, "/");
+			}
 
 			/* May get empty procargs */
 			if (!strstr(procargs, argv[0]) && strstr(procargs, process_string) && strcmp(procargs,"")) {
@@ -145,14 +139,7 @@
 	}
 
 	/* If we get anything on stderr, at least set warning */
-	while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
-		result = max_state (result, STATE_WARNING);
-
-	/* close stderr */
-	(void) fclose (child_stderr);
-
-	/* close the pipe */
-	if (spclose (child_process))
+	if(chld_err.buflen)
 		result = max_state (result, STATE_WARNING);
 
 	/* reset the alarm handler */
diff -urN ../nplg/plugins/check_ping.c ./plugins/check_ping.c
--- ../nplg/plugins/check_ping.c	2005-05-26 14:12:21.000000000 +0200
+++ ./plugins/check_ping.c	2005-06-10 15:01:26.000000000 +0200
@@ -14,18 +14,18 @@
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
- $Id: check_ping.c,v 1.44 2005/05/25 14:25:55 sghosh Exp $
+ $Id: check_ping.c,v 1.2 2005/06/05 21:55:26 exon Exp $
  
 ******************************************************************************/
 
 const char *progname = "check_ping";
-const char *revision = "$Revision: 1.44 $";
+const char *revision = "$Revision: 1.2 $";
 const char *copyright = "2000-2004";
 const char *email = "nagiosplug-devel@lists.sourceforge.net";
 
 #include "common.h"
 #include "netutils.h"
-#include "popen.h"
+#include "runcmd.h"
 #include "utils.h"
 
 #define WARN_DUPLICATES "DUPLICATES FOUND! "
@@ -40,7 +40,7 @@
 int get_threshold (char *, float *, int *);
 int validate_arguments (void);
 int run_ping (const char *cmd, const char *addr);
-int error_scan (char buf[MAX_INPUT_BUFFER], const char *addr);
+int error_scan (const char *buf, const char *addr);
 void print_usage (void);
 void print_help (void);
 
@@ -58,7 +58,7 @@
 float rta = UNKNOWN_TRIP_TIME;
 int pl = UNKNOWN_PACKET_LOSS;
 
-char *warn_text;
+char *warn_text = NULL;
 
 
 
@@ -95,10 +95,8 @@
 		if (is_inet6_addr(addresses[i]) && address_family != AF_INET)
 			rawcmd = strdup(PING6_COMMAND);
 		else
-			rawcmd = strdup(PING_COMMAND);
-#else
-		rawcmd = strdup(PING_COMMAND);
 #endif
+			rawcmd = strdup(PING_COMMAND);
 
 		/* does the host address of number of packets argument come first? */
 #ifdef PING_PACKETS_FIRST
@@ -119,8 +117,7 @@
 
 		if (pl == UNKNOWN_PACKET_LOSS || rta < 0.0) {
 			printf ("%s\n", cmd);
-			die (STATE_UNKNOWN,
-			           _("CRITICAL - Could not interpret output from ping command\n"));
+			die (STATE_UNKNOWN, _("CRITICAL - Could not interpret output from ping command\n"));
 		}
 
 		if (pl >= cpl || rta >= crta || rta < 0)
@@ -136,11 +133,11 @@
 		if (display_html == TRUE)
 			printf ("<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@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@lists.sourceforge.net";
 
 #include "common.h"
 #include "utils.h"
-#include "popen.h"
+#include "runcmd.h"
 
 #define DEFAULT_COMMUNITY "public"
 #define DEFAULT_PORT "161"
@@ -136,11 +136,12 @@
 	char *command_line = NULL;
 	char *response = NULL;
 	char *outbuff;
-	char *output;
+	char *msg;
 	char *ptr = NULL;
 	char *p2 = NULL;
 	char *show = NULL;
 	char type[8];
+	output chld_out, chld_err;
 
 	setlocale (LC_ALL, "");
 	bindtextdomain (PACKAGE, LOCALEDIR);
@@ -157,7 +158,7 @@
 	units = strdup ("");
 	port = strdup (DEFAULT_PORT);
 	outbuff = strdup ("");
-	output = strdup ("");
+	msg = strdup ("");
 	delimiter = strdup (" = ");
 	output_delim = strdup (DEFAULT_OUTPUT_DELIMITER);
 	/* miblist = strdup (DEFAULT_MIBLIST); */
@@ -168,41 +169,25 @@
 		usage4 (_("Could not parse arguments"));
 
 	/* create the command line to execute */
-		if(usesnmpgetnext == TRUE) {
-		asprintf(&command_line, "%s -t %d -r %d -m %s -v %s %s %s:%s %s",
-				    PATH_TO_SNMPGETNEXT, timeout_interval, retries, miblist, proto,
-						authpriv, server_address, port, oid);
-	}else{
-
-		asprintf (&command_line, "%s -t %d -r %d -m %s -v %s %s %s:%s %s",
-	          PATH_TO_SNMPGET, timeout_interval, retries, miblist, proto,
-	          authpriv, server_address, port, oid);
-	}
-	
+	asprintf(&command_line, "%s -t %d -r %d -m %s -v %s %s %s:%s %s",
+	         usesnmpgetnext == TRUE ? PATH_TO_SNMPGETNEXT : PATH_TO_SNMPGET,
+	         timeout_interval, retries, miblist, proto,
+	         authpriv, server_address, port, oid);
+
 	if (verbose)
 		printf ("%s\n", command_line);
-	
 
 	/* run the command */
-	child_process = spopen (command_line);
-	if (child_process == NULL) {
-		printf (_("Could not open pipe: %s\n"), command_line);
-		exit (STATE_UNKNOWN);
-	}
-
-	child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
-	if (child_stderr == NULL) {
-		printf (_("Could not open stderr for %s\n"), command_line);
-	}
+	if((np_runcmd(command_line, &chld_out, &chld_err, 0)) != 0 || chld_err.buflen)
+		result = STATE_WARNING;
 
-	while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process))
-		asprintf (&output, "%s%s", output, input_buffer);
+	for(i = 0; (size_t)i < chld_out.lines; i++)
+		asprintf (&msg, "%s%s", msg, input_buffer);
 
 	if (verbose)
-		printf ("%s\n", output);
-
-	ptr = output;
+		printf ("%s\n", msg);
 
+	ptr = msg;
 	strcat(perfstr, "| ");
 	while (ptr) {
 		char *foo;
@@ -261,18 +246,11 @@
 		iresult = STATE_DEPENDENT;
 
 		/* Process this block for integer comparisons */
-		if (eval_method[i] & CRIT_GT ||
-		    eval_method[i] & CRIT_LT ||
-		    eval_method[i] & CRIT_GE ||
-		    eval_method[i] & CRIT_LE ||
-		    eval_method[i] & CRIT_EQ ||
-		    eval_method[i] & CRIT_NE ||
-		    eval_method[i] & WARN_GT ||
-		    eval_method[i] & WARN_LT ||
-		    eval_method[i] & WARN_GE ||
-		    eval_method[i] & WARN_LE ||
-		    eval_method[i] & WARN_EQ ||
-		    eval_method[i] & WARN_NE) {
+		if (eval_method[i] & (CRIT_GT | CRIT_LT | CRIT_GE |
+		                      CRIT_LE | CRIT_EQ | CRIT_NE |
+		                      WARN_GT | WARN_LT | WARN_GE |
+		                      WARN_LE | WARN_EQ | WARN_NE))
+		{
 			p2 = strpbrk (p2, "0123456789");
 			if (p2 == NULL) 
 				die (STATE_UNKNOWN,_("No valid data returned"));
@@ -350,20 +328,6 @@
 		     label,
 		     command_line);
 
-	/* WARNING if output found on stderr */
-	if (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
-		result = max_state (result, STATE_WARNING);
-
-	/* close stderr */
-	(void) fclose (child_stderr);
-
-	/* close the pipe */
-	if (spclose (child_process))
-		result = max_state (result, STATE_WARNING);
-
-/* 	if (nunits == 1 || i == 1) */
-/* 		printf ("%s %s -%s %s\n", label, state_text (result), outbuff, units); */
-/* 	else */
 	printf ("%s %s -%s %s \n", label, state_text (result), outbuff, perfstr);
 
 	return result;
diff -urN ../nplg/plugins/check_swap.c ./plugins/check_swap.c
--- ../nplg/plugins/check_swap.c	2005-01-24 08:29:54.000000000 +0100
+++ ./plugins/check_swap.c	2005-06-10 15:01:26.000000000 +0200
@@ -21,18 +21,18 @@
  *
  * Copyright (c) 2000 Karl DeBisschop (kdebisschop@users.sourceforge.net)
  *
- * $Id: check_swap.c,v 1.47 2005/01/19 21:14:47 tonvoon Exp $
+ * $Id: check_swap.c,v 1.4 2005/06/06 11:37:06 exon Exp $
  *
  *****************************************************************************/
 
 const char *progname = "check_swap";
-const char *revision = "$Revision: 1.47 $";
+const char *revision = "$Revision: 1.4 $";
 const char *copyright = "2000-2004";
 const char *email = "nagiosplug-devel@lists.sourceforge.net";
 
 #include "common.h"
-#include "popen.h"
 #include "utils.h"
+#include "runcmd.h"
 
 int check_swap (int usp, float free_swap);
 int process_arguments (int argc, char **argv);
@@ -64,6 +64,8 @@
 	char *temp_buffer;
 	char *swap_command;
 	char *swap_format;
+	output chld_out, chld_err;
+	size_t i = 0;
 # else
 #  ifdef HAVE_DECL_SWAPCTL
 	int i=0, nswaps=0, swapctl_res=0;
@@ -79,14 +81,13 @@
 # endif
 #endif
 	char str[32];
-	char *status, *tmp_status;
+	char *status;
 
 	setlocale (LC_ALL, "");
 	bindtextdomain (PACKAGE, LOCALEDIR);
 	textdomain (PACKAGE);
 
 	status = strdup ("");
-	tmp_status = strdup ("");
 	perf = strdup ("");
 
 	if (process_arguments (argc, argv) == ERROR)
@@ -146,15 +147,9 @@
 	if (verbose >= 3)
 		printf (_("Format: %s\n"), swap_format);
 
-	child_process = spopen (swap_command);
-	if (child_process == NULL) {
-		printf (_("Could not open pipe: %s\n"), swap_command);
-		return STATE_UNKNOWN;
-	}
-
-	child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
-	if (child_stderr == NULL)
-		printf (_("Could not open stderr for %s\n"), swap_command);
+	/* run the command. set WARNING if non-zero return or output on stderr */
+	if((np_runcmd(swap_command, &chld_out, &chld_err, 0)) || chld_err.buflen)
+		result = STATE_WARNING;
 
 	sprintf (str, "%s", "");
 	/* read 1st line */
@@ -210,17 +205,6 @@
 #  ifdef _AIX
 	}
 #  endif
-
-	/* If we get anything on STDERR, at least set warning */
-	while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
-		result = max_state (result, STATE_WARNING);
-
-	/* close stderr */
-	(void) fclose (child_stderr);
-
-	/* close the pipe */
-	if (spclose (child_process))
-		result = max_state (result, STATE_WARNING);
 # else
 #  ifdef CHECK_SWAP_SWAPCTL_SVR4
 
@@ -314,16 +298,19 @@
 	percent_used = 100 * ((double) used_swap) / ((double) total_swap);
 	result = max_state (result, check_swap (percent_used, free_swap));
 	/* broken into two steps because of funkiness with builtin asprintf */
-	asprintf (&tmp_status, _(" %d%% free (%.0f MB out of %.0f MB)"),
-						(100 - percent_used), free_swap, total_swap);
-	asprintf (&status, "%s%s", tmp_status, status);
-
-	asprintf (&perf, "%s", perfdata ("swap", (long) free_swap, "MB",
-		TRUE, (long) max (warn_size/1024, warn_percent/100.0*total_swap),
-		TRUE, (long) max (crit_size/1024, crit_percent/100.0*total_swap),
-		TRUE, 0,
-		TRUE, (long) total_swap));
-	printf ("SWAP %s:%s |%s\n", state_text (result), status, perf);
+	/* the breaking was removed because it was stupid. There's no reason
+	 * to concatenate a string using asprintf() just to print it to stdout
+	 * in the next statement. */
+	printf (_("SWAP %s - %d%% free (%.0f MB out of %.0f MB) %s|"),
+			state_text (result),
+			(100 - percent_used), free_swap, total_swap, status);
+
+	puts (perfdata ("swap", (long) free_swap, "MB",
+	                TRUE, (long) max (warn_size/1024, warn_percent/100.0*total_swap),
+	                TRUE, (long) max (crit_size/1024, crit_percent/100.0*total_swap),
+	                TRUE, 0,
+	                TRUE, (long) total_swap));
+
 	return result;
 }
 
@@ -383,7 +370,7 @@
 			}
 			else if (strstr (optarg, ",") &&
 							 strstr (optarg, "%") &&
-							 sscanf (optarg, "%.0f,%d%%", &warn_size, &warn_percent) == 2) {
+							 sscanf (optarg, "%f,%d%%", &warn_size, &warn_percent) == 2) {
 				break;
 			}
 			else if (strstr (optarg, "%") &&
@@ -400,7 +387,7 @@
 			}
 			else if (strstr (optarg, ",") &&
 							 strstr (optarg, "%") &&
-							 sscanf (optarg, "%.0f,%d%%", &crit_size, &crit_percent) == 2) {
+							 sscanf (optarg, "%f,%d%%", &crit_size, &crit_percent) == 2) {
 				break;
 			}
 			else if (strstr (optarg, "%") &&
diff -urN ../nplg/plugins/check_users.c ./plugins/check_users.c
--- ../nplg/plugins/check_users.c	2005-01-05 21:53:22.000000000 +0100
+++ ./plugins/check_users.c	2005-06-10 15:01:26.000000000 +0200
@@ -14,17 +14,17 @@
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
- $Id: check_users.c,v 1.19 2004/12/25 23:17:44 opensides Exp $
+ $Id: check_users.c,v 1.2 2005/06/05 21:55:26 exon Exp $
  
 *****************************************************************************/
 
 const char *progname = "check_users";
-const char *revision = "$Revision: 1.19 $";
+const char *revision = "$Revision: 1.2 $";
 const char *copyright = "2000-2004";
 const char *email = "nagiosplug-devel@lists.sourceforge.net";
 
 #include "common.h"
-#include "popen.h"
+#include "runcmd.h"
 #include "utils.h"
 
 #define possibly_set(a,b) ((a) == 0 ? (b) : 0)
@@ -41,52 +41,28 @@
 {
 	int users = -1;
 	int result = STATE_UNKNOWN;
-	char input_buffer[MAX_INPUT_BUFFER];
-	char *perf;
+	output chld_out, chld_err;
+	size_t i;
 
 	setlocale (LC_ALL, "");
 	bindtextdomain (PACKAGE, LOCALEDIR);
 	textdomain (PACKAGE);
 
-	perf = strdup("");
-
 	if (process_arguments (argc, argv) == ERROR)
 		usage4 (_("Could not parse arguments"));
 
 	/* run the command */
-	child_process = spopen (WHO_COMMAND);
-	if (child_process == NULL) {
-		printf (_("Could not open pipe: %s\n"), WHO_COMMAND);
-		return STATE_UNKNOWN;
-	}
-
-	child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
-	if (child_stderr == NULL)
-		printf (_("Could not open stderr for %s\n"), WHO_COMMAND);
-
-	users = 0;
-
-	while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
-
-		/* increment 'users' on all lines except total user count */
-		if (input_buffer[0] != '#') {
-			users++;
-			continue;
-		}
-
-		/* get total logged in users */
-		if (sscanf (input_buffer, _("# users=%d"), &users) == 1)
-			break;
-
-	}
+	result = np_runcmd(WHO_COMMAND, &chld_out, &chld_err, 0);
+	if(result != 0)
+		result = STATE_UNKNOWN;
+
+	/* one user is listed per line, except when it begins with '#' */
+	users = chld_out.lines;
+	for(i = 0; i < chld_out.lines; i++)
+		if (chld_out.line[0][0] == '#') users--;
 
 	/* check STDERR */
-	if (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
-		result = possibly_set (result, STATE_UNKNOWN);
-	(void) fclose (child_stderr);
-
-	/* close the pipe */
-	if (spclose (child_process))
+	if(chld_err.buflen > 0)
 		result = possibly_set (result, STATE_UNKNOWN);
 
 	/* else check the user count against warning and critical thresholds */
@@ -98,16 +74,12 @@
 		result = STATE_OK;
 
 	if (result == STATE_UNKNOWN)
-		printf (_("Unable to read output\n"));
-	else {
-		asprintf(&perf, "%s", perfdata ("users", users, "",
-		  TRUE, wusers,
-		  TRUE, cusers,
-		  TRUE, 0,
-		  FALSE, 0));
-		printf (_("USERS %s - %d users currently logged in |%s\n"), state_text (result),
-		  users, perf);
-	}
+		die (STATE_UNKNOWN, _("Unable to read output\n"));
+
+	printf (_("USERS %s - %d users currently logged in |%s\n"),
+	        state_text (result), users,
+	        perfdata("users", users, "",
+	                 TRUE, wusers, TRUE, cusers, TRUE, 0, FALSE, 0));
 
 	return result;
 }
@@ -129,8 +101,10 @@
 		{0, 0, 0, 0}
 	};
 
-	if (argc < 2)
-		usage ("\n");
+	if (argc < 2) {
+		print_usage ();
+		exit(STATE_UNKNOWN);
+	}
 
 	while (1) {
 		c = getopt_long (argc, argv, "+hVvc:w:", longopts, &option);
diff -urN ../nplg/plugins/foo ./plugins/foo
--- ../nplg/plugins/foo	1970-01-01 01:00:00.000000000 +0100
+++ ./plugins/foo	2005-06-10 15:05:25.000000000 +0200
@@ -0,0 +1,12 @@
+$Id: check_by_ssh.c,v 1.35 2004/12/25 12:09:19 opensides Exp $
+$Id: check_dig.c,v 1.40 2005/01/26 21:21:01 tonvoon Exp $
+$Id: check_dns.c,v 1.47 2004/12/30 00:41:39 opensides Exp $
+$Id: check_fping.c,v 1.24 2004/12/25 23:17:44 opensides Exp $
+$Id: check_load.c,v 1.28 2005/05/28 01:21:54 seanius Exp $
+$Id: check_nagios.c,v 1.26 2005/05/25 00:43:20 seanius Exp $
+$Id: check_ping.c,v 1.44 2005/05/25 14:25:55 sghosh Exp $
+$Id: check_procs.c,v 1.45 2005/06/03 13:53:43 seanius Exp $
+$Id: check_snmp.c,v 1.57 2005/06/01 19:41:01 sghosh Exp $
+$Id: check_users.c,v 1.19 2004/12/25 23:17:44 opensides Exp $
+$Id: negate.c,v 1.24 2004/12/25 23:17:44 opensides Exp $
+$Id: urlize.c,v 1.17 2004/12/25 23:17:44 opensides Exp $
diff -urN ../nplg/plugins/Makefile.am ./plugins/Makefile.am
--- ../nplg/plugins/Makefile.am	2005-02-15 09:28:36.000000000 +0100
+++ ./plugins/Makefile.am	2005-06-10 15:01:26.000000000 +0200
@@ -24,7 +24,8 @@
 	check_nagios check_by_ssh check_dns check_nt check_ide_smart	\
 	check_procs
 
-EXTRA_DIST = t utils.c netutils.c popen.c utils.h netutils.h popen.h common.h \
+EXTRA_DIST = t common.h utils.c utils.h netutils.c netutils.h \
+	runcmd.c runcmd.h \
 	getaddrinfo.c getaddrinfo.h gethostbyname.c gethostbyname.h
 
 PLUGINHDRS = common.h
@@ -46,85 +47,85 @@
 # the actual targets
 
 check_dhcp_LDADD = $(NETLIBS)
-check_dig_LDADD = $(NETLIBS) popen.o 
-check_disk_LDADD = $(BASEOBJS) popen.o
-check_dns_LDADD = $(NETLIBS) popen.o
+check_dig_LDADD = $(NETLIBS) runcmd.o 
+check_disk_LDADD = $(BASEOBJS) runcmd.o
+check_dns_LDADD = $(NETLIBS) runcmd.o
 check_dummy_LDADD = $(BASEOBJS)
-check_fping_LDADD = $(NETLIBS) popen.o
-check_game_LDADD = $(BASEOBJS) popen.o
+check_fping_LDADD = $(NETLIBS) runcmd.o
+check_game_LDADD = $(BASEOBJS) runcmd.o
 check_http_LDADD = $(NETLIBS) $(SSLLIBS)
-check_hpjd_LDADD = $(NETLIBS) popen.o
+check_hpjd_LDADD = $(NETLIBS) runcmd.o
 check_icmp_LDADD = $(SOCKETLIBS)
 check_ldap_LDADD = $(NETLIBS) $(LDAPLIBS)
-check_load_LDADD = $(BASEOBJS) popen.o
+check_load_LDADD = $(BASEOBJS) runcmd.o
 check_mrtg_LDADD = $(BASEOBJS)
 check_mrtgtraf_LDADD = $(BASEOBJS)
 check_mysql_LDADD = $(NETLIBS) $(MYSQLLIBS)
-check_nagios_LDADD = $(BASEOBJS) popen.o
+check_nagios_LDADD = $(BASEOBJS) runcmd.o
 check_nt_LDADD = $(NETLIBS) 
 check_nwstat_LDADD = $(NETLIBS)
 check_overcr_LDADD = $(NETLIBS)
 check_pgsql_LDADD = $(NETLIBS) $(PGLIBS)
-check_ping_LDADD = $(NETLIBS) popen.o
-check_procs_LDADD = $(BASEOBJS) popen.o
+check_ping_LDADD = $(NETLIBS) runcmd.o
+check_procs_LDADD = $(BASEOBJS) runcmd.o
 check_radius_LDADD = $(NETLIBS) $(RADIUSLIBS)
 check_real_LDADD = $(NETLIBS)
-check_snmp_LDADD = $(BASEOBJS) popen.o
+check_snmp_LDADD = $(BASEOBJS) runcmd.o
 check_smtp_LDADD = $(NETLIBS) $(SSLLIBS)
 check_ssh_LDADD = $(NETLIBS)
-check_swap_LDADD = $(BASEOBJS) popen.o
+check_swap_LDADD = $(BASEOBJS) runcmd.o
 check_tcp_LDADD = $(NETLIBS) $(SSLLIBS)
 check_time_LDADD = $(NETLIBS)
 check_udp_LDADD = $(NETLIBS)
 check_ups_LDADD = $(NETLIBS)
-check_users_LDADD = $(BASEOBJS) popen.o
-check_by_ssh_LDADD = $(NETLIBS) popen.o
+check_users_LDADD = $(BASEOBJS) runcmd.o
+check_by_ssh_LDADD = $(NETLIBS) runcmd.o
 check_ide_smart_LDADD = $(BASEOBJS)
-negate_LDADD = $(BASEOBJS) popen.o
-urlize_LDADD = $(BASEOBJS) popen.o
+negate_LDADD = $(BASEOBJS) runcmd.o
+urlize_LDADD = $(BASEOBJS) runcmd.o
 
 check_dhcp_DEPENDENCIES = check_dhcp.c $(NETOBJS) $(DEPLIBS) 
-check_dig_DEPENDENCIES = check_dig.c $(NETOBJS) popen.o $(DEPLIBS)
-check_disk_DEPENDENCIES = check_disk.c $(BASEOBJS) popen.o $(DEPLIBS)
-check_dns_DEPENDENCIES = check_dns.c $(NETOBJS) popen.o $(DEPLIBS)
+check_dig_DEPENDENCIES = check_dig.c $(NETOBJS) runcmd.o $(DEPLIBS)
+check_disk_DEPENDENCIES = check_disk.c $(BASEOBJS) runcmd.o $(DEPLIBS)
+check_dns_DEPENDENCIES = check_dns.c $(NETOBJS) runcmd.o $(DEPLIBS)
 check_dummy_DEPENDENCIES = check_dummy.c $(DEPLIBS)
-check_fping_DEPENDENCIES = check_fping.c $(NETOBJS) popen.o $(DEPLIBS)
+check_fping_DEPENDENCIES = check_fping.c $(NETOBJS) runcmd.o $(DEPLIBS)
 check_game_DEPENDENCIES = check_game.c  $(DEPLIBS)
 check_http_DEPENDENCIES = check_http.c $(NETOBJS) $(DEPLIBS)
-check_hpjd_DEPENDENCIES = check_hpjd.c $(NETOBJS) popen.o $(DEPLIBS)
+check_hpjd_DEPENDENCIES = check_hpjd.c $(NETOBJS) runcmd.o $(DEPLIBS)
 check_icmp_DEPENDENCIES = check_icmp.c
 check_ide_smart_DEPENDENCIES = check_ide_smart.c $(BASEOBJS) $(DEPLIBS)
 check_ldap_DEPENDENCIES = check_ldap.c $(NETOBJS) $(DEPLIBS)
-check_load_DEPENDENCIES = check_load.c $(BASEOBJS) popen.o $(DEPLIBS)
+check_load_DEPENDENCIES = check_load.c $(BASEOBJS) runcmd.o $(DEPLIBS)
 check_mrtg_DEPENDENCIES = check_mrtg.c $(DEPLIBS)
 check_mrtgtraf_DEPENDENCIES = check_mrtgtraf.c $(DEPLIBS)
 check_mysql_DEPENDENCIES = check_mysql.c $(NETOBJS) $(DEPLIBS)
-check_nagios_DEPENDENCIES = check_nagios.c $(BASEOBJS) popen.o $(DEPLIBS)
+check_nagios_DEPENDENCIES = check_nagios.c $(BASEOBJS) runcmd.o $(DEPLIBS)
 check_nt_DEPENDENCIES = check_nt.c $(NETOBJS) $(DEPLIBS)
 check_nwstat_DEPENDENCIES = check_nwstat.c $(NETOBJS) $(DEPLIBS)
 check_overcr_DEPENDENCIES = check_overcr.c $(NETOBJS) $(DEPLIBS)
 check_pgsql_DEPENDENCIES = check_pgsql.c $(NETOBJS)  $(DEPLIBS)
-check_ping_DEPENDENCIES = check_ping.c $(NETOBJS) popen.o $(DEPLIBS)
-check_procs_DEPENDENCIES = check_procs.c $(BASEOBJS) popen.o $(DEPLIBS)
+check_ping_DEPENDENCIES = check_ping.c $(NETOBJS) runcmd.o $(DEPLIBS)
+check_procs_DEPENDENCIES = check_procs.c $(BASEOBJS) runcmd.o $(DEPLIBS)
 check_radius_DEPENDENCIES = check_radius.c $(NETOBJS)  $(DEPLIBS)
 check_real_DEPENDENCIES = check_real.c $(NETOBJS) $(DEPLIBS)
-check_snmp_DEPENDENCIES = check_snmp.c $(BASEOBJS) popen.o $(DEPLIBS)
+check_snmp_DEPENDENCIES = check_snmp.c $(BASEOBJS) runcmd.o $(DEPLIBS)
 check_smtp_DEPENDENCIES = check_smtp.c $(NETOBJS) $(DEPLIBS)
 check_ssh_DEPENDENCIES = check_ssh.c $(NETOBJS) $(DEPLIBS)
-check_swap_DEPENDENCIES = check_swap.c $(BASEOBJS) popen.o $(DEPLIBS)
+check_swap_DEPENDENCIES = check_swap.c $(BASEOBJS) runcmd.o $(DEPLIBS)
 check_tcp_DEPENDENCIES = check_tcp.c $(NETOBJS) $(DEPLIBS)
 check_time_DEPENDENCIES = check_time.c $(NETOBJS) $(DEPLIBS)
 check_udp_DEPENDENCIES = check_udp.c $(NETOBJS) $(DEPLIBS)
 check_ups_DEPENDENCIES = check_ups.c $(NETOBJS) $(DEPLIBS)
-check_users_DEPENDENCIES = check_users.c $(BASEOBJS) popen.o $(DEPLIBS)
-check_by_ssh_DEPENDENCIES = check_by_ssh.c $(NETOBJS) popen.o $(DEPLIBS)
-negate_DEPENDENCIES = negate.c $(BASEOBJS) popen.o $(DEPLIBS)
-urlize_DEPENDENCIES = urlize.c $(BASEOBJS) popen.o $(DEPLIBS)
+check_users_DEPENDENCIES = check_users.c $(BASEOBJS) runcmd.o $(DEPLIBS)
+check_by_ssh_DEPENDENCIES = check_by_ssh.c $(NETOBJS) runcmd.o $(DEPLIBS)
+negate_DEPENDENCIES = negate.c $(BASEOBJS) runcmd.o $(DEPLIBS)
+urlize_DEPENDENCIES = urlize.c $(BASEOBJS) runcmd.o $(DEPLIBS)
 
 ##############################################################################
 # secondary dependencies
 
-popen.o: popen.c popen.h $(PLUGINHDRS)
+runcmd.o: runcmd.c runcmd.h $(PLUGINHDRS)
 
 utils.o: utils.c utils.h $(PLUGINHDRS)
 
diff -urN ../nplg/plugins/negate.c ./plugins/negate.c
--- ../nplg/plugins/negate.c	2005-01-05 21:53:22.000000000 +0100
+++ ./plugins/negate.c	2005-06-10 15:01:26.000000000 +0200
@@ -14,7 +14,7 @@
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  
- $Id: negate.c,v 1.24 2004/12/25 23:17:44 opensides Exp $
+ $Id: negate.c,v 1.2 2005/06/05 21:55:26 exon Exp $
 
 @@-<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@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@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@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;
 }
