+# ordinalize(1) => "1st"
+# ordinalize(2) => "2nd"
+# ordinalize(3) => "3rd"
+# ordinalize(111) => "111th"
+# ordinalize("62") => "62nd"
+function ordinalize($i) {
+ return $i . ordinal_suffix($i);
+}
+
+# remove the $key from $_REQUEST and return it's value (or null if it's not there)
+function _REQUEST_cut($key) {
+ if(!isset($_REQUEST[$key])) {
+ return null;
+ }
+ $ret = $_REQUEST[$key];
+ unset($_REQUEST[$key]);
+ return $ret;
+}
+
+# returns an array containing just the elements of $pipes that are readable (without blocking)
+# timeout 0 means don't wait, timeout NULL means wait indefinitely
+function readable_sockets($pipes, $timeout = 0){
+ $read = array_values($pipes);
+ $ret = stream_select($read, $write = NULL, $exceptions = NULL, $timeout);
+ if($ret === false) {
+ return false;
+ }
+ if($ret) {
+ return $read;
+ } else {
+ return array();
+ }
+}
+
+
+# Parameters:
+# command
+# stdin
+# Returns: (as array)
+# exit code
+# stdout
+function exec_pipe($command, $stdin) {
+ $descriptorspec = array(
+ 0 => array('pipe', 'r'), // stdin is a pipe that the child will read from
+ 1 => array('pipe', 'w'), // stdout is a pipe that the child will write to
+ 2 => array('file', '/dev/null', 'w') // stderr is a pipe that the child will write to
+ );
+
+ $process = proc_open($command, $descriptorspec, $pipes);
+
+ if (is_resource($process)) {
+ fwrite($pipes[0], $stdin);
+ fclose($pipes[0]);
+
+ while (!feof($pipes[1])) {
+ $chunk = fread($pipes[1], 1024);
+ $stdout .= $chunk;
+ sleep(0.5);
+ }
+
+ fclose($pipes[1]);
+
+ // It is important that you close any pipes before calling
+ // proc_close in order to avoid a deadlock
+ $return_value = proc_close($process);
+
+ return array($return_value, $stdout);
+ }
+}
+
+