Index: common/common.php
===================================================================
--- common/common.php	(revision 1184)
+++ common/common.php	(working copy)
@@ -4,12 +4,15 @@
 // commabelow to cedille and returns the modified text
 // FIXME: reverse characters in to_change when windows XP dies
 function text_change_special_chars($text) {
+    if (!extension_loaded('mbstring')) {
+        return $text;
+    }
+
     $to_change = array("ș"=>"ş", "ț"=>"ţ", "Ș"=>"Ş", "Ț"=>"Ţ");
 
     foreach ($to_change as $bad=>$good) {
         $text = mb_ereg_replace($bad, $good, $text);
     }
-
     return $text;
 }
 
@@ -323,7 +326,8 @@ function check_requirements() {
         log_warn("zip extension missing.");
     }
     if (array_search('mbstring', $extensions) === false) {
-        log_warn("mbstring extension missing. inline diff will not be enabled");
+        log_warn('mbstring extension missing. inline diff and ' .
+                 'character normalisation will not be available.');
     }
     if (!function_exists("finfo_open")) {
         log_warn('finfo_open missing, falling back to mime_content_type.');
Index: eval/BaseGrader.php
===================================================================
--- eval/BaseGrader.php	(revision 1184)
+++ eval/BaseGrader.php	(working copy)
@@ -3,12 +3,11 @@
 require_once(IA_ROOT_DIR."common/task.php");
 
 abstract class BaseGrader {
-    protected $task, $tparams, $job;
+    protected $task, $job;
     protected $result, $testResults;
 
     public function __construct($task, $tparams, $job) {
-        $this->task = $task;
-        $this->tparams = $tparams;
+        $this->task = array_merge($task, $tparams);
         $this->job = $job;
     }
 
@@ -19,8 +18,6 @@ abstract class BaseGrader {
      * The interactive program is used in 'interactive' tasks. This program is
      * run in parallel with the user's program and comunication between them
      * is implemented through pipes.
-     *
-     * @return boolean          true on success, false on error
      */
     protected function compileEvaluators() {
         $evals = array(
@@ -36,72 +33,46 @@ abstract class BaseGrader {
             if (!copy_grader_file($this->task, $this->task[$eval_type],
                                   $source_file)) {
                 log_print("Task $eval_type not found");
-                $this->result = array(
-                    'score' => 0,
-                    'message' => 'Eroare in setarile problemei',
-                    'log' => ("Lipseste $eval_desc.\n" .
-                              "Ar trebui sa existe un atasament ".
-                              "'grader_{$this->task[$eval_type]}' " .
-                              "la pagina cu enuntul problemei"),
-                );
-                return false;
+                throw new EvalTaskOwnerError(
+                    "Lipşeşte {$eval_desc}.\nPagina cu enunţul problemei " .
+                    "trebuie să conţină un ataşament 'grader_" .
+                    $this->task[$eval_type] . "'");
             }
 
             $compiler_messages = '';
             if (!compile_file($source_file, $eval_type, $compiler_messages)) {
                 log_print("Task $eval_type compile error");
-                $this->result = array(
-                    'score' => 0,
-                    'message' => "Eroare de compilare in $eval_desc",
-                    'log' => ("Eroare de compilare in $eval_desc:\n" .
-                              $compiler_messages),
-                );
-                return false;
+                throw new EvalTaskOwnerError('Eroare de compilare în ' .
+                                             $eval_desc . ":\n" .
+                                             $compiler_messages);
             }
         }
-        return true;
     }
 
     /**
      * Processes the user submission. For classic and interactive tasks, this
      * means compiling the user's source file.
-     *
-     * @return boolean          true on success, false on error
      */
     protected function processUserSubmission() {
         $source_file = 'user.' . $this->job['compiler_id'];
-        if (file_put_contents($source_file,
-                              $this->job['file_contents']) === false) {
-            log_print('User program could not be written to disk');
-            $this->result = array(
-                'score' => 0,
-                'message' => 'Eroare de sistem',
-                'log' => 'Contacteaza un administrator',
-            );
-            return false;
-        }
+        $res = @file_put_contents($source_file,
+                                  $this->job['file_contents']);
+        eval_assert($res !== false,
+                    'User program could not be written to disk');
 
         $compiler_messages = '';
         if (!compile_file($source_file, 'user', $compiler_messages)) {
             log_print('User program compile error');
             log_print($compiler_messages);
-            $this->result = array(
-                'score' => 0,
-                'message' => 'Eroare de compilare',
-                'log' => "Eroare de compilare:\n" . $compiler_messages,
-            );
-            return false;
+            throw new EvalUserCompileError($compiler_messages);
         }
         $this->result['log'] = "Compilare:\n" . $compiler_messages . "\n";
-        return true;
     }
 
     /**
      * Perform any necessary actions before running test cases.
      * These include compiling evaluators or interactive programs and
      * compiling user source files.
-     *
-     * @return boolean          true on success, false on error
      */
     protected function preTestCases() {
         $this->result = array(
@@ -111,38 +82,26 @@ abstract class BaseGrader {
         );
 
         // Clean temporary directory and chdir to it
-        $ret = clean_dir(IA_ROOT_DIR . 'eval/temp/');
-        log_assert($ret, "Can't clean to temp dir.");
-        $ret = chdir(IA_ROOT_DIR . 'eval/temp/');
-        log_assert($ret, "Can't chdir to temp dir.");
+        eval_assert(clean_dir(IA_ROOT_DIR . 'eval/temp/'),
+                    "Can't clean temp dir.");
+        eval_assert(@chdir(IA_ROOT_DIR . 'eval/temp/'),
+                    "Can't chdir to temp dir.");
 
         // Compile all source files
-        if (!$this->compileEvaluators()) {
-            return false;
-        }
-        if (!$this->processUserSubmission()) {
-            return false;
-        }
-        return true;
+        $this->compileEvaluators();
+        $this->processUserSubmission();
     }
 
     /**
      * Perform any necessary actions after running all test cases.
-     *
-     * @return boolean          true on success, false on error
      */
     protected function postTestCases() {
         $this->result['message'] = 'Evaluare completa';
         if ($this->result['score'] < 0 ||
             $this->result['score'] > IA_JUDGE_MAX_SCORE) {
-            $this->result = array(
-                'score' => 0,
-                'message' => 'Eroare in evaluatorul problemei',
-                'log' => 'Evaluatorul a returnat un scor invalid.',
-            );
-            return false;
+            throw new EvalTaskOwnerError(
+                'Evaluatorul a returnat un scor invalid.');
         }
-        return true;
     }
 
     protected function getInFile($jaildir) {
@@ -157,17 +116,11 @@ abstract class BaseGrader {
         return $jaildir . $this->task['id'] . '.ok';
     }
 
-    protected function getUserFile($jaildir, $testno) {
-        // FIXME: jrun does not work with absolute paths because of chroot
-        return 'user_' . $this->job['id'] . '_' . $testno;
-    }
-
     /**
      * Evaluates the contestant's output on a particular test case.
      *
      * @param  int     $testno
      * @param  string  $jaildir
-     * @return bool                  true on success, false on failure
      */
     protected function testCaseJudgeOutputs($testno, $jaildir) {
         $test_result = &$this->testResults[$testno];
@@ -179,15 +132,10 @@ abstract class BaseGrader {
             if (!copy_grader_file($this->task, 'test' . $testno . '.ok',
                                   $okfile)) {
                 log_print("Test $testno: .ok file not found");
-                $this->result = array(
-                    'score' => 0,
-                    'message' => 'Eroare in testele problemei',
-                    'log' => ("Lipseste fisierul .ok al testului $testno.\n" .
-                              "Ar trebui sa existe un atasament".
-                              " 'grader_test$testno.ok' ".
-                              "la pagina cu enuntul problemei"),
-                );
-                return false;
+                throw new EvalTaskOwnerError(
+                    "Lipşeşte fişierul .ok al testului $testno.\nPagina cu " .
+                    "enunţul problemei trebuie să conţină un ataşament " .
+                    "'grader_test{$testno}.ok'");
             }
         }
 
@@ -211,35 +159,30 @@ abstract class BaseGrader {
                 $test_result['message'] = 'Fisier de iesire lipsa';
                 $test_result['score'] = 0;
             }
-            return true;
+            return;
         }
 
         // Custom grader.
-        $ret = copy(IA_ROOT_DIR . 'eval/temp/evaluator',
-                    $jaildir . 'evaluator');
-        log_assert($ret, "Failed copying custom grader");
-        $ret = chmod('evaluator', 0555);
-        log_assert("Failed to chmod a+x user program");
+        $ret = @copy(IA_ROOT_DIR . 'eval/temp/evaluator',
+                     $jaildir . 'evaluator');
+        eval_assert($ret, 'Failed to copy custom grader');
+        eval_assert(chmod('evaluator', 0555),
+                    'Failed to chmod a+x user program');
 
         // Run task eval, and check result
         $jrunres = jail_run('evaluator', $jaildir,
                             IA_JUDGE_TASK_EVAL_TIMELIMIT,
                             IA_JUDGE_TASK_EVAL_MEMLIMIT,
                             true);
-        log_assert($jrunres['result'] != 'ERROR', "Error in jrun");
+        eval_assert($jrunres['result'] != 'ERROR', "Error in jrun");
 
         // Task eval is not allowed to fail.
         if ($jrunres['result'] == 'FAIL') {
             log_print("Test $testno: Task eval failed");
-            $this->result = array(
-                'score' => 0,
-                'message' => 'Eroare in evaluatorul problemei',
-                'log' => ("A aparut o eroare in rularea evaluatorului ".
-                          "pe testul $testno: {$jrunres['message']}".
-                          ": timp {$jrunres['time']}ms".
-                          ": mem {$jrunres['memory']}kb"),
-            );
-            return false;
+            throw new EvalTaskOwnerError(
+                "A apărut o eroare în rularea evaluatorului pe testul " .
+                "$testno: {$jrunres['message']}: timp {$jrunres['time']}ms: " .
+                "mem {$jrunres['memory']}kb");
         }
 
         // Get score.
@@ -247,13 +190,9 @@ abstract class BaseGrader {
         if ($jrunres['stdout'] === '' ||
             !is_whole_number($jrunres['stdout'])) {
             log_print("Test $testno: Task eval score broken or empty");
-            $this->result = array(
-                'score' => 0,
-                'message' => 'Eroare in evaluatorul problemei',
-                'log' => ("Evaluatorul nu a returnat un numar la stdout ".
-                          "pe testul $testno (se ignora spatii, newline, etc)"),
-            );
-            return false;
+            throw new EvalTaskOwnerError(
+                "Evaluatorul nu a returnat un număr la stdout " .
+                "pe testul $testno (se ignoră spaţii, newline, etc)");
         }
 
         $test_result['grader_time'] = $jrunres['time'];
@@ -262,39 +201,25 @@ abstract class BaseGrader {
         if ($test_result['score'] < 0 ||
             $test_result['score'] > IA_JUDGE_MAX_SCORE) {
             log_print("Test $testno: Invalid score returned by evaluator");
-            $this->result = array(
-                'score' => 0,
-                'message' => 'Eroare in evaluatorul problemei',
-                'log' => 'Evaluatorul a returnat un scor invalid.',
-            );
-            return false;
+            throw new EvalTaskOwnerError(
+                'Evaluatorul a returnat un scor invalid.');
         }
 
         // Get message.
         $message = $jrunres['stderr'];
-        $match = array();
-        if (!preg_match("/^([^\n]*)/i", $message, $match)) {
-            log_error("Broken preg_match???");
-        }
-        $message = $match[1];
-        if (strpos($message, "\n") ||
+        $message = strtok($message, "\n");
+        if (strlen($message) == 0 ||
             strlen($message) > IA_JUDGE_MAX_EVAL_MESSAGE) {
             log_print("Test $testno: Task eval message broken");
-            $this->result = array(
-                'score' => 0,
-                'message' => 'Eroare in evaluatorul problemei',
-                'log' =>
-                    ('Evaluatorul a returnat un mesaj mai lung de ' .
-                     IA_JUDGE_MAX_EVAL_MESSAGE . 'de caractere la stdout'),
-            );
-            return false;
+            throw new EvalTaskOwnerError(
+                'Evaluatorul a returnat un mesaj gol sau mai lung de ' .
+                IA_JUDGE_MAX_EVAL_MESSAGE . 'de caractere la stdout');
         }
         $test_result['message'] = $message;
 
         // Log.
         log_print("Test $testno: Eval gave {$test_result['score']} points " .
                   "and said {$test_result['message']}");
-        return true;
     }
 
     /**
@@ -304,7 +229,6 @@ abstract class BaseGrader {
      *
      * @param  int     $testno
      * @param  string  $jaildir
-     * @return bool                  true on success, false on failure
      */
     abstract protected function testCaseJudge($testno, $jaildir);
 
@@ -315,9 +239,7 @@ abstract class BaseGrader {
      *                          fields
      */
     public function grade() {
-        if (!$this->preTestCases()) {
-            return $this->result;
-        }
+        $this->preTestCases();
 
         // Running tests.
         $this->testResults = array();
@@ -336,14 +258,10 @@ abstract class BaseGrader {
                 }
 
                 // Clean and chdir to jail dir.
-                $ret = clean_dir($jaildir);
-                log_assert($ret, "Can't clean jail dir.");
-                $ret = chdir($jaildir);
-                log_assert($ret, "Can't chdir to jail dir.");
+                eval_assert(clean_dir($jaildir), "Can't clean jail dir.");
+                eval_assert(@chdir($jaildir), "Can't chdir to jail dir.");
 
-                if (!$this->testCaseJudge($testno, $jaildir)) {
-                    return $this->result;
-                }
+                $this->testCaseJudge($testno, $jaildir);
                 $test_result = &$this->testResults[$testno];
                 job_test_update($this->job['id'], $testno, $group_idx,
                                 $test_result['test_time'],
Index: eval/ClassicGrader.php
===================================================================
--- eval/ClassicGrader.php	(revision 1184)
+++ eval/ClassicGrader.php	(working copy)
@@ -6,8 +6,9 @@ class ClassicGrader extends BaseGrader {
     protected function testCaseJudge($testno, $jaildir) {
         $this->testResults[$testno] = array();
         $test_result = &$this->testResults[$testno];
+
         $infile = $this->getInFile($jaildir);
-        $userfile = $this->getUserFile($jaildir, $testno);
+        $userfile = 'user_' . $this->job['id'] . '_' . $testno;
 
         // HACK: Capture run-time stderr for Python jobs.
         //
@@ -23,25 +24,21 @@ class ClassicGrader extends BaseGrader {
         if (!copy_grader_file($this->task, 'test' . $testno . '.in',
                               $infile)) {
             log_print("Test $testno: input not found");
-            $this->result = array(
-                'score' => 0,
-                'message' => 'Eroare in teste',
-                'log' => ("Lipseste intrarea testului $testno.\n" .
-                          "Ar trebui sa existe un atasament".
-                          " 'grader_test$testno.in' ".
-                          "la pagina cu enuntul problemei"),
-            );
-            return false;
+            throw new EvalTaskOwnerError(
+                "Lipşeşte intrarea testului {$testno}.\nPagina cu " .
+                "enunţul problemei trebuie să conţină un ataşament " .
+                "'grader_test{$testno}.in'");
         }
 
-        $ret = copy(IA_ROOT_DIR.'eval/temp/user', $userfile);
-        log_assert($ret, "Failed copying user program");
-        $ret = chmod($userfile, 0555);
-        log_assert("Failed to chmod a+x user program");
+        // Copy user executable
+        eval_assert(@copy(IA_ROOT_DIR.'eval/temp/user', $userfile),
+                    'Failed to copy user program');
+        eval_assert(@chmod($userfile, 0555),
+                    'Failed to chmod a+x user program');
 
         // Run user program on a test case.
-        $timelimit = $this->tparams['timelimit'] * 1000;
-        $memlimit = $this->tparams['memlimit'];
+        $timelimit = $this->task['timelimit'] * 1000;
+        $memlimit = $this->task['memlimit'];
         // Adjust time and memory limit for Python jobs.
         if ('py' == $this->job['compiler_id']) {
             $timelimit *= 4.0;
@@ -52,8 +49,8 @@ class ClassicGrader extends BaseGrader {
                             (int)$timelimit,
                             (int)$memlimit,
                             $capture_std);
-        log_assert($jrunres['result'] != 'ERROR',
-                   'Error in jrun: ' . $jrunres['message']);
+        eval_assert($jrunres['result'] != 'ERROR',
+                    'Error in jrun: ' . $jrunres['message']);
         if ($jrunres['result'] == 'FAIL') {
             log_print("Test $testno: User program failed: " .
                       $jrunres['message'] . ' ' . $jrunres['time'] .
@@ -76,16 +73,13 @@ class ClassicGrader extends BaseGrader {
                 'message' => $message,
             );
             // User program failed on this test. Bye bye.
-            return true;
+            return;
         }
 
         $test_result = array(
             'test_time' => $jrunres['time'],
             'test_mem' => $jrunres['memory'],
         );
-        if (!$this->testCaseJudgeOutputs($testno, $jaildir)) {
-            return false;
-        }
-        return true;
+        $this->testCaseJudgeOutputs($testno, $jaildir);
     }
 }
Index: eval/Exceptions.php
new file mode 100644
===================================================================
--- eval/Exceptions.php	(revision 0)
+++ eval/Exceptions.php	(working copy)
@@ -0,0 +1,44 @@
+<?php
+
+abstract class EvalException extends Exception {
+    abstract public function getShortMessage();
+}
+
+final class EvalSystemError extends EvalException {
+    public function __construct($message, $code = 0,
+                                Exception $previous = null) {
+        parent::__construct("Contactează un administrator\n" . $message,
+                            $code, $previous);
+    }
+
+    public function getShortMessage() {
+        return 'Eroare de sistem';
+    }
+}
+
+final class EvalTaskOwnerError extends EvalException {
+    public function __construct($message, $code = 0,
+                                Exception $previous = null) {
+        parent::__construct("Contactează autorul problemei:\n" . $message,
+                            $code, $previous);
+    }
+
+    public function getShortMessage() {
+        return 'Eroare în configurarea problemei';
+    }
+}
+
+abstract class EvalUserError extends EvalException {
+}
+
+final class EvalUserCompileError extends EvalUserError {
+    public function __construct($message, $code = 0,
+                                Exception $previous = null) {
+        parent::__construct("Eroare de compilare:\n" . $message,
+                            $code, $previous);
+    }
+
+    public function getShortMessage() {
+        return 'Eroare de compilare';
+    }
+}
Index: eval/download.php
===================================================================
--- eval/download.php	(revision 1184)
+++ eval/download.php	(working copy)
@@ -3,8 +3,7 @@
 require_once(IA_ROOT_DIR . 'common/common.php');
 require_once(IA_ROOT_DIR . 'common/db/attachment.php');
 
-function copy_grader_file($task, $filename, $target)
-{
+function copy_grader_file($task, $filename, $target) {
     $attempts = 0;
     while (true) {
         $result = copy_attachment_file($task['page_name'], "grader_".$filename, $target);
@@ -25,11 +24,12 @@ function copy_grader_file($task, $filename, $target)
 // This will download the file from the server and cache it.
 //
 // Return success value.
-function copy_attachment_file($pagename, $filename, $target)
-{
+function copy_attachment_file($pagename, $filename, $target) {
     $pagename = normalize_page_name($pagename);
-    log_assert(is_page_name($pagename), "Invalid page name '$pagename'");
-    log_assert(is_attachment_name($filename), "Invalid attachment name '$filename'");
+    eval_assert(is_page_name($pagename),
+                "Invalid page name '$pagename'");
+    eval_assert(is_attachment_name($filename),
+                "Invalid attachment name '$filename'");
 
     // Get attachment from database.
     $att = attachment_get($filename, $pagename);
@@ -99,5 +99,3 @@ function copy_attachment_file($pagename, $filename, $target)
     }
     return true;
 }
-
-?>
Index: eval/eval
===================================================================
--- eval/eval	(revision 1184)
+++ eval/eval	(working copy)
@@ -16,6 +16,7 @@ require_once(IA_ROOT_DIR.'common/db/user.php');
 
 require_once(IA_ROOT_DIR.'eval/utilities.php');
 require_once(IA_ROOT_DIR.'eval/download.php');
+require_once(IA_ROOT_DIR.'eval/Exceptions.php');
 require_once(IA_ROOT_DIR.'eval/ClassicGrader.php');
 
 error_reporting(0xFFFF);
@@ -53,7 +54,15 @@ function job_handle($job) {
     } else {
         log_error("Nu stiu sa evaluez task-uri de tip ".$task['type']);
     }
-    $job_result = $grader->grade();
+    try {
+        $job_result = $grader->grade();
+    } catch (EvalException $e) {
+        $job_result = array(
+            'score' => 0,
+            'message' => $e->getShortMessage(),
+            'log' => $e->getMessage(),
+        );
+    }
 
     $submit_count = 0;
     /**
Index: eval/utilities.php
===================================================================
--- eval/utilities.php	(revision 1184)
+++ eval/utilities.php	(working copy)
@@ -7,26 +7,31 @@ function milisleep($ms) {
 
 // Delete and remake a directory.
 // Return success value.
-function clean_dir($dir)
-{
-    system("rm -rf " . $dir, $res);
-    if (mkdir($dir, 0777, true) === false) {
+function clean_dir($dir) {
+    system("rm -rf " . $dir);
+    if (@mkdir($dir, 0777, true) === false) {
         log_warn("Failed re-creating directory $dir");
         return false;
     }
-    if (chmod($dir, 0777) == false) {
+    if (@chmod($dir, 0777) == false) {
         log_warn("Failed chmod 0777 directory $dir");
         return false;
     }
     return true;
 }
 
+function eval_assert($condition, $message = 'Assertion Error') {
+    if (!$condition) {
+        log_print('Evaluator assertion failed: ' . $message);
+        throw new EvalSystemError($message);
+    }
+}
+
 // Compile a certain file.
 // Returns success value, and a friendly error message in $compiler_message.
 //
 // Can currently handle C, C++, FreePascal, and Python.
-function compile_file($input_file_name, $output_file_name, &$compiler_message)
-{
+function compile_file($input_file_name, $output_file_name, &$compiler_message) {
     $compiler_message = false;
     $compiler_lines = array(
             // Make sure -lm stays after source file & target output
@@ -36,7 +41,9 @@ function compile_file($input_file_name, $output_file_name, &$compiler_message)
             'fpc' => 'fpc -O2 -Xs %file_name%',
             'py' => IA_JUDGE_PY_COMPILER.' %file_name% %exe_name%',
     );
-    if (!preg_match("/^(.*)\.(c|cpp|pas|fpc|py)$/i", $input_file_name, $matches)) {
+    $matches = array();
+    if (!preg_match("/^(.*)\.(c|cpp|pas|fpc|py)$/i",
+                    $input_file_name, $matches)) {
         $compiler_message = "Nu am putut sa determin compilatorul ".
                 "pentru '$input_file_name'.";
         return false;
@@ -62,10 +69,8 @@ function compile_file($input_file_name, $output_file_name, &$compiler_message)
 
     // Rename to $output_file_name.
     if ($exe_name != $output_file_name) {
-        if (!@rename($exe_name, $output_file_name)) {
-            log_error("Failed renaming $exe_name to $output_file_name");
-            return false;
-        }
+        eval_assert(@rename($exe_name, $output_file_name),
+                    "Failed renaming $exe_name to $output_file_name");
     }
 
     // Hooray!
@@ -78,8 +83,8 @@ function compile_file($input_file_name, $output_file_name, &$compiler_message)
 // Result is 'OK', 'FAIL' or 'ERROR'
 // If result is ERROR time and memory are not available
 // Returns false on error.
-function jrun_parse_message($message)
-{
+function jrun_parse_message($message) {
+    $matches = array();
     if (!preg_match("/^(ERROR|FAIL|OK):\ (.*)$/", $message, $matches)) {
         log_warn("Invalid jrun output: $message");
         return false;
@@ -106,8 +111,7 @@ function jrun_parse_message($message)
 
 // Returns a jrun message array for an error.
 // Sort of a hack.
-function jrun_make_error($message)
-{
+function jrun_make_error($message) {
     return array('result' => "ERROR", 'message' => $message);
 }
 
@@ -130,10 +134,10 @@ function jrun_make_error($message)
 // All timings are in miliseconds and memory is in kilobytes
 //
 // If result is ERROR time, memory, stdin and stdout are never set.
-function jail_run($program, $jaildir, $time, $memory, $capture_std = false)
-{
-    log_assert(is_whole_number($time));
-    log_assert(is_whole_number($memory));
+function jail_run($program, $jaildir, $time, $memory, $capture_std = false) {
+    eval_assert(is_whole_number($time));
+    eval_assert(is_whole_number($memory));
+
     $cmdline = IA_ROOT_DIR . 'jrun/jrun';
     $cmdline .= " --prog=./" . $program;
     $cmdline .= " --dir=" . $jaildir;
@@ -181,14 +185,10 @@ function jail_run($program, $jaildir, $time, $memory, $capture_std = false)
     }
 
     if ($result['result'] == 'OK') {
-        if ($result['time'] > $time || $result['memory'] > $memory) {
-            log_print_r($result);
-            log_print("time $time memory $memory limits");
-            log_error("JRun says ok, but limits broken");
-        }
+        eval_assert($result['time'] <= $jrun_process['time'] &&
+                    $result['memory'] <= $jrun_process['memory'],
+                    'JRun returns OK, but time or memory limit is broken');
     }
 
     return $result;
 }
-
-?>
Index: jrun/Makefile
===================================================================
--- jrun/Makefile	(revision 1184)
+++ jrun/Makefile	(working copy)
@@ -9,11 +9,13 @@ test: jrun force
 	./run-tests.php
 
 clean: force
-	rm -rf jrun jrun.o options.o names.o
+	rm -f jrun.o options.o names.o
+
+dist-clean: force clean
+	rm -f jrun
 
 jrun: jrun.c jrun.h options.c names.c
 	gcc -Wall -O2 jrun.c -c -o jrun.o
 	gcc -Wall -O2 options.c -c -o options.o
 	gcc -Wall -O2 names.c -c -o names.o
 	gcc -o jrun jrun.o options.o names.o
-	
