Example #1
0
 /**
  * @param array
  * @param array
  * @param array
  * @return int
  * */
 public function _exec(array $argv, array $envp, array $redirections)
 {
     $descriptors = $this->descriptors;
     foreach ($redirections as $n => $redirection) {
         if (is_array($redirection)) {
             if (($handle = @fopen($redirection[1], $redirection[0])) === FALSE) {
                 throw new Error('cannot open file ' . $redirection[1]);
             }
             $descriptors[$n] = $handle;
         } else {
             assert(is_int($redirection));
             if (!isset($descriptors[$redirection])) {
                 throw new Error('bad file descriptor ' . $redirection);
             }
             $descriptors[$n] = $descriptors[$redirection];
         }
     }
     // BREAK
     if ($argv[0] === 'break') {
         $n = 1;
         if (isset($argv[1])) {
             $n = intval($argv[1]);
         }
         throw new BuiltinBreak($n);
         // COLON
     } else {
         if ($argv[0] === ':') {
             $this->variables['?'] = 0;
         } else {
             if ($argv[0] === 'continue') {
                 $n = 1;
                 if (isset($argv[1])) {
                     $n = intval($argv[1]);
                 }
                 throw new BuiltinContinue($n);
                 // DOT
             } else {
                 if ($argv[0] === '.') {
                     if (!(isset($argv[1]) && ($contents = file_get_contents($argv[1])) !== FALSE)) {
                         if (!isset($argv[1])) {
                             throw new Error('.: no file given');
                         } else {
                             throw new Error('.: cannot read file');
                         }
                     }
                     $saved_can_read = $this->can_read;
                     $this->can_read = FALSE;
                     $saved_tokens = $this->tokens;
                     $this->tokens = $this->tokenize($contents);
                     $saved_descriptors = $this->descriptors;
                     $this->descriptors = $descriptors;
                     try {
                         $this->interpretMoreCommands();
                     } catch (BuiltinReturn $r) {
                         $this->variables['?'] = $r->getExitStatus();
                     }
                     $this->can_read = $saved_can_read;
                     $this->tokens = $saved_tokens;
                     $this->descriptors = $saved_descriptors;
                     // EVAL
                 } else {
                     if ($argv[0] === 'eval') {
                         $newtokens = $this->tokenize(implode(' ', array_slice($argv, 1)));
                         if (end($newtokens) === ';') {
                             array_pop($newtokens);
                         }
                         $this->tokens = array_merge(array(';'), $newtokens, $this->tokens);
                         // EXEC
                     } else {
                         if ($argv[0] === 'exec') {
                             if (count($argv) > 1) {
                                 fwrite($descriptors[2], "exec: only file descriptors handling implemented\n");
                                 $this->variables['?'] = 255;
                             } else {
                                 $this->descriptors = $descriptors;
                                 $this->variables['?'] = 0;
                             }
                             // EXIT
                         } else {
                             if ($argv[0] === 'exit') {
                                 $n = 0;
                                 if (isset($argv[1])) {
                                     $n = intval($argv[1]);
                                 }
                                 throw new BuiltinExit($n);
                                 // EXPORT
                             } else {
                                 if ($argv[0] === 'export') {
                                     if (isset($argv[1]) && $argv[1] === '-p') {
                                         foreach ($this->exported as $exported => $_) {
                                             if (isset($this->variables[$exported])) {
                                                 fprintf($descriptors[1], "export %s='%s'\n", $exported, $this->variables[$exported]);
                                             } else {
                                                 fprintf($descriptors[1], "export %s\n", $exported);
                                             }
                                         }
                                     } else {
                                         foreach (array_slice($argv, 1) as $variable) {
                                             if (strpos($variable, '=') !== FALSE) {
                                                 list($variable, $value) = explode('=', $variable, 2);
                                                 $this->variables[$variable] = $value;
                                             }
                                             $this->exported[$variable] = TRUE;
                                         }
                                     }
                                     $this->variables['?'] = 0;
                                     // READONLY
                                 } else {
                                     if ($argv[0] === 'readonly') {
                                         fwrite($descriptors[2], "readonly: currently not supported\n");
                                         $this->variables['?'] = 255;
                                         // RETURN
                                     } else {
                                         if ($argv[0] === 'return') {
                                             $n = 0;
                                             if (isset($argv[1])) {
                                                 $n = intval($argv[1]);
                                             }
                                             throw new BuiltinReturn($n);
                                             // SET
                                         } else {
                                             if ($argv[0] === 'set') {
                                                 fwrite($descriptors[2], "set: currently not supported\n");
                                                 $this->variables['?'] = 255;
                                                 // SHIFT
                                             } else {
                                                 if ($argv[0] === 'shift') {
                                                     $n = 1;
                                                     if (isset($argv[1])) {
                                                         $n = intval($argv[1]);
                                                     }
                                                     for ($i = 1, $c = count($this->argv); $i < $c; ++$i) {
                                                         unset($this->variables[$i]);
                                                     }
                                                     foreach (array_slice($this->argv, count($this->argv) - $this->variables['#'] + $n) as $i => $arg) {
                                                         $this->variables[$i + 1] = $arg;
                                                     }
                                                     $this->variables['#'] = $this->variables['#'] - $n;
                                                     $this->variables['?'] = 0;
                                                     // TIMES
                                                 } else {
                                                     if ($argv[0] === 'times') {
                                                         fwrite($descriptors[2], "times: currently not supported\n");
                                                         $this->variables['?'] = 255;
                                                         // TRAP
                                                     } else {
                                                         if ($argv[0] === 'trap') {
                                                             fwrite($descriptors[2], "trap: currently not supported\n");
                                                             $this->variables['?'] = 255;
                                                             // UNSET
                                                         } else {
                                                             if ($argv[0] === 'unset') {
                                                                 if (count($argv) < 2) {
                                                                     fwrite($descriptors[2], "unset: [-fv] name...\n");
                                                                     $this->variables['?'] = 255;
                                                                 } else {
                                                                     if ($argv[1] === '-f') {
                                                                         foreach (array_slice($argv, 2) as $function) {
                                                                             unset($this->functions[$function]);
                                                                         }
                                                                     } else {
                                                                         $variables = array_slice($argv, 1);
                                                                         if ($argv[1] === '-v') {
                                                                             $variables = array_slice($argv, 2);
                                                                         }
                                                                         foreach ($variables as $variable) {
                                                                             unset($this->variables[$variable]);
                                                                         }
                                                                     }
                                                                     $this->variables['?'] = 0;
                                                                 }
                                                                 // FUNCTION?
                                                             } else {
                                                                 if (isset($this->functions[$argv[0]])) {
                                                                     $saved_argv = $this->argv;
                                                                     $this->argv = $argv;
                                                                     $saved_envp = $this->envp;
                                                                     $this->envp = $envp;
                                                                     $saved_variables = $this->variables;
                                                                     $this->variables = array();
                                                                     $this->variables['#'] = count($argv) - 1;
                                                                     foreach ($argv as $k => $v) {
                                                                         $this->variables[$k] = $v;
                                                                     }
                                                                     $saved_can_read = $this->can_read;
                                                                     $this->can_read = FALSE;
                                                                     $saved_tokens = $this->tokens;
                                                                     $this->tokens = $this->functions[$argv[0]];
                                                                     $this->interpretMoreCommands();
                                                                     $saved_variables['?'] = isset($this->variables['?']) ? $this->variables['?'] : 0;
                                                                     $this->argv = $saved_argv;
                                                                     $this->envp = $saved_envp;
                                                                     $this->variables = $saved_variables;
                                                                     $this->can_read = $saved_can_read;
                                                                     $this->tokens = $saved_tokens;
                                                                     return $this->variables['?'];
                                                                     // EXTERNAL EXECUTOR
                                                                 } else {
                                                                     $this->variables['?'] = $this->executor->exec($argv, $envp, $descriptors);
                                                                     if ($this->variables['?'] === 127 && $this->interactive) {
                                                                         fwrite($this->stderr, "sh: " . $argv[0] . " not found\r\n");
                                                                     }
                                                                     return $this->variables['?'];
                                                                 }
                                                             }
                                                         }
                                                     }
                                                 }
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
 }