Index: /branches/eam_branches/ipp-pstamp-20260421/PS-IPP-Config/lib/PS/IPP/Config.pm
===================================================================
--- /branches/eam_branches/ipp-pstamp-20260421/PS-IPP-Config/lib/PS/IPP/Config.pm	(revision 43050)
+++ /branches/eam_branches/ipp-pstamp-20260421/PS-IPP-Config/lib/PS/IPP/Config.pm	(revision 43051)
@@ -46,4 +46,5 @@
                     caturi
                     file_scheme
+                    ps_run
                     );
 our %EXPORT_TAGS = (standard => [@EXPORT_OK]);
@@ -1754,4 +1755,74 @@
 }
 
+sub ps_run {
+
+    my %args = @_;
+
+    unless (exists $args{command}) { carp "Missing command argument in ps_run\n"; }
+    my $command = $args{command};
+
+    my $verbose = 0;
+    if (exists $args{verbose}) { $verbose = $args{verbose}; }
+
+    # print "command: $command\n";
+
+    my ( $success, $error_msg, $full_buf, $stdout_buf, $stderr_buf ) = run(command => $command, verbose => $verbose);
+
+    ## upon success, we can just return
+    if (defined $success && $success) {
+	my $error_code = 0;
+	return ($success, $error_code, $full_buf, $stdout_buf, $stderr_buf);
+    }
+
+    my $error_code = 0;
+
+    ## old-style IPC::Cmd returns an error code in the second argument:
+    if ($IPC::Cmd::VERSION < 0.40) {
+	$error_code = $error_msg;
+    } else {
+	if (defined $error_msg) {
+	    if ($error_msg =~ /exited with value (\d+)/) {
+		$error_code = $1 << 8;
+	    } elsif ($error_msg =~ /died with signal (\d+)/) {
+		$error_code = $1;            # signal in low byte, same as waitpid
+	    } elsif ($error_msg =~ /open3: exec/) {
+		$error_code = 0x200;        # missing executable
+	    } else {
+		$error_code = 0x400;        # unknown failure (
+	    }
+	} else {
+	    $error_code = 0x800;        # unknown failure
+	}
+    }
+    return ($success, $error_code, $full_buf, $stdout_buf, $stderr_buf);
+}
+
+# this is a basic utility to support both old and new versions of IPC::Cmd run
+# if the program exited normally, the exit value is returned
+# if the program exited with a signal (abort, crash, etc), PS_EXIT_PROG_ERROR (4) is returned
+# if the program failed to run, -PS_EXIT_PROG_ERROR (-4) is returned
+sub parse_error_message_alt {
+    my $success = shift;
+    my $error_msg = shift;
+    my $command = shift;
+
+    if ($success) { return 0; }
+
+    print "raw error_msg: $error_msg\n";
+    print "full command: $command\n";
+
+    if (&looks_like_number($error_msg)) { return (($error_msg >> 8) or ($PS_EXIT_PROG_ERROR)); }
+	
+    # which of these match?
+    my ($error_code) = $error_msg =~ m/exited with value (\d+)/;
+    if (defined $error_code) { return $error_code; }
+    
+    ($error_code) = $error_msg =~ m/died with signal (\d+)/;
+#   if (defined $error_code) { return (128 + $error_code); }
+    if (defined $error_code) { return ($PS_EXIT_PROG_ERROR); }
+    
+    # probably failed to execute:
+    return (-1*$PS_EXIT_PROG_ERROR);
+}
 
 1;
