--- /dev/null
+<?php
+/* calc.php - NeonServ v5.6
+ * Copyright (C) 2011-2012 Philipp Kreil (pk910)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+$text = implode(" ", array_slice($argv, 1));
+
+$descriptor = array(0 => array("pipe", "r"),1 => array("pipe", "w"),2 => array("pipe", "w"));
+$proc = proc_open('bc -l -q', $descriptor, $pipes);
+
+if(!is_resource($proc)) {
+ echo"internal calc error - please contact an administrator.\n";
+ die();
+}
+
+fwrite($pipes[0], $text."\nquit\n");
+
+$start = time();
+
+$read=array($pipes[1]);
+$write=NULL;
+$except=NULL;
+
+while(1) {
+ $data = proc_get_status($proc);
+ if(!$data['running']) {
+ $out="";
+ while(!feof($pipes[1])) {
+ $out .= fgets($pipes[1], 128);
+ }
+ if($out == "") {
+ $out="\0034";
+ while(!feof($pipes[2])) {
+ $out .= fgets($pipes[2], 128);
+ }
+ $out.="";
+ }
+ $out=str_replace("\n","",$out);
+ $out=str_replace("\r","",$out);
+ $out=str_replace("\\","",$out);
+
+ if(strlen($text) > 20) {
+ if(strlen($out) > 450) {
+ echo "output too long (".strlen($out).")\n";
+ } else {
+ echo "".$text."\n";
+ echo $out."\n";
+ }
+ } else {
+ $fout="".$text." = ".$out;
+ if(strlen($fout) > 450) {
+ echo "output too long (".strlen($out).")";
+ } else {
+ echo $fout."\n";
+ }
+ }
+
+ fclose($pipes[0]);
+ fclose($pipes[1]);
+ fclose($pipes[2]);
+ proc_close($proc);
+
+ die();
+ } else {
+
+ if($start+3 > time()) {
+ usleep(200000); //200ms
+ } else {
+ //TIMEOUT
+ fclose($pipes[0]);
+ fclose($pipes[1]);
+ fclose($pipes[2]);
+ //can't simply use proc_terminate: https://bugs.php.net/bug.php?id=39992
+ $ppid = $data['pid'];
+ //use ps to get all the children of this process, and kill them
+ $pids = preg_split('/\s+/', `ps -o pid --no-heading --ppid $ppid`);
+ foreach($pids as $pid) {
+ if(is_numeric($pid)) {
+ posix_kill($pid, 9); //SIGKILL signal
+ }
+ }
+ proc_close($proc);
+ echo "calculator timeout. (maximum of 3 seconds exceeded)\n";
+ die();
+ }
+ }
+}
+
+?>