diff --git a/extlib/System/Command.php b/extlib/System/Command.php deleted file mode 100644 index f5c3ec6b92..0000000000 --- a/extlib/System/Command.php +++ /dev/null @@ -1,587 +0,0 @@ - | -// | Author: Dan Allen -// +----------------------------------------------------------------------+ - -// $Id: Command.php,v 1.9 2007/04/20 21:08:48 cconstantine Exp $ - -// }}} -// {{{ includes - -require_once 'PEAR.php'; -require_once 'System.php'; - -// }}} -// {{{ constants - -define('SYSTEM_COMMAND_OK', 1); -define('SYSTEM_COMMAND_ERROR', -1); -define('SYSTEM_COMMAND_NO_SHELL', -2); -define('SYSTEM_COMMAND_INVALID_SHELL', -3); -define('SYSTEM_COMMAND_TMPDIR_ERROR', -4); -define('SYSTEM_COMMAND_INVALID_OPERATOR', -5); -define('SYSTEM_COMMAND_INVALID_COMMAND', -6); -define('SYSTEM_COMMAND_OPERATOR_PLACEMENT',-7); -define('SYSTEM_COMMAND_COMMAND_PLACEMENT', -8); -define('SYSTEM_COMMAND_NOHUP_MISSING', -9); -define('SYSTEM_COMMAND_NO_OUTPUT', -10); -define('SYSTEM_COMMAND_STDERR', -11); -define('SYSTEM_COMMAND_NONZERO_EXIT', -12); - -// }}} - -// {{{ class System_Command - -/** - * The System_Command:: class implements an abstraction for various ways - * of executing commands (directly using the backtick operator, - * as a background task after the script has terminated using - * register_shutdown_function() or as a detached process using nohup). - * - * @author Anders Johannsen - * @author Dan Allen - * @version $Revision: 1.9 $ - */ - -// }}} -class System_Command { - // {{{ properties - - /** - * Array of settings used when creating the shell command - * - * @var array - * @access private - */ - var $options = array(); - - /** - * Array of available shells to use to execute the command - * - * @var array - * @access private - */ - var $shells = array(); - - /** - * Array of available control operators used between commands - * - * @var array - * @access private - */ - var $controlOperators = array(); - - /** - * The system command to be executed - * - * @var string - * @access private - */ - var $systemCommand = null; - - /** - * Previously added part to the command string - * - * @var string - * @access private - */ - var $previousElement = null; - - /** - * Directory for writing stderr output - * - * @var string - * @access private - */ - var $tmpDir = null; - - /** - * To allow the pear error object to accumulate when building - * the command, we use the command status to keep track when - * a pear error is raised - * - * @var int - * @access private - */ - var $commandStatus = 0; - - /** - * Hold initialization PEAR_Error - * - * @var object - * @access private - **/ - var $_initError = null; - - // }}} - // {{{ constructor - - /** - * Class constructor - * - * Defines all necessary constants and sets defaults - * - * @access public - */ - function System_Command($in_shell = null) - { - // Defining constants - $this->options = array( - 'SEQUENCE' => true, - 'SHUTDOWN' => false, - 'SHELL' => $this->which($in_shell), - 'OUTPUT' => true, - 'NOHUP' => false, - 'BACKGROUND' => false, - 'STDERR' => false - ); - - // prepare the available control operators - $this->controlOperators = array( - 'PIPE' => '|', - 'AND' => '&&', - 'OR' => '||', - 'GROUP' => ';', - 'LFIFO' => '<', - 'RFIFO' => '>', - ); - - // List of allowed/available shells - $this->shells = array( - 'sh', - 'bash', - 'zsh', - 'tcsh', - 'csh', - 'ash', - 'sash', - 'esh', - 'ksh' - ); - - // Find the first available shell - if (empty($this->options['SHELL'])) { - foreach ($this->shells as $shell) { - if ($this->options['SHELL'] = $this->which($shell)) { - break; - } - } - - // see if we still have no shell - if (empty($this->options['SHELL'])) { - $this->_initError =& PEAR::raiseError(null, SYSTEM_COMMAND_NO_SHELL, null, E_USER_WARNING, null, 'System_Command_Error', true); - return; - } - } - - // Caputre a temporary directory for capturing stderr from commands - $this->tmpDir = System::tmpdir(); - if (!System::mkDir("-p {$this->tmpDir}")) { - $this->_initError =& PEAR::raiseError(null, SYSTEM_COMMAND_TMPDIR_ERROR, null, E_USER_WARNING, null, 'System_Command_Error', true); - return; - } - } - - // }}} - // {{{ setOption() - - /** - * Sets the value for an option. Each option should be set to true - * or false; except the 'SHELL' option which should be a string - * naming a shell. The options are: - * - * 'SEQUENCE' Allow a sequence command or not (right now this is always on); - * - * 'SHUTDOWN' Execute commands via a shutdown function; - * - * 'SHELL' Path to shell; - * - * 'OUTPUT' Output stdout from process; - * - * 'NOHUP' Use nohup to detach process; - * - * 'BACKGROUND' Run as a background process with &; - * - * 'STDERR' Output on stderr will raise an error, even if - * the command's exit value is zero. The output from - * stderr can be retrieved using the getDebugInfo() - * method of the Pear_ERROR object returned by - * execute().; - * - * @param string $in_option is a case-sensitive string, - * corresponding to the option - * that should be changed - * @param mixed $in_setting is the new value for the option - * @access public - * @return bool true if succes, else false - */ - function setOption($in_option, $in_setting) - { - if ($this->_initError) { - return $this->_initError; - } - - $option = strtoupper($in_option); - - if (!isset($this->options[$option])) { - PEAR::raiseError(null, SYSTEM_COMMAND_ERROR, null, E_USER_NOTICE, null, 'System_Command_Error', true); - return false; - } - - switch ($option) { - case 'OUTPUT': - case 'SHUTDOWN': - case 'SEQUENCE': - case 'BACKGROUND': - case 'STDERR': - $this->options[$option] = !empty($in_setting); - return true; - break; - - case 'SHELL': - if (($shell = $this->which($in_setting)) !== false) { - $this->options[$option] = $shell; - return true; - } - else { - PEAR::raiseError(null, SYSTEM_COMMAND_NO_SHELL, null, E_USER_NOTICE, $in_setting, 'System_Command_Error', true); - return false; - } - break; - - case 'NOHUP': - if (empty($in_setting)) { - $this->options[$option] = false; - } - else if ($location = $this->which('nohup')) { - $this->options[$option] = $location; - } - else { - PEAR::raiseError(null, SYSTEM_COMMAND_NOHUP_MISSING, null, E_USER_NOTICE, null, 'System_Command_Error', true); - return false; - } - break; - } - } - - // }}} - // {{{ pushCommand() - - /** - * Used to push a command onto the running command to be executed - * - * @param string $in_command binary to be run - * @param string $in_argument either an option or argument value, to be handled appropriately - * @param string $in_argument - * @param ... - * - * @access public - * @return boolean true on success {or System_Command_Error Exception} - */ - function pushCommand($in_command) - { - if ($this->_initError) { - return $this->_initError; - } - - if (!is_null($this->previousElement) && !in_array($this->previousElement, $this->controlOperators)) { - $this->commandStatus = -1; - $error = PEAR::raiseError(null, SYSTEM_COMMAND_COMMAND_PLACEMENT, null, E_USER_WARNING, null, 'System_Command_Error', true); - } - - // check for error here - $command = escapeshellcmd($this->which($in_command)); - if ($command === false) { - $error = PEAR::raiseError(null, SYSTEM_COMMAND_INVALID_COMMAND, null, E_USER_WARNING, null, 'System_Command_Error', true); - } - - $argv = func_get_args(); - array_shift($argv); - foreach($argv as $arg) { - if (strpos($arg, '-') === 0) { - $command .= ' ' . $arg; - } - elseif ($arg != '') { - $command .= ' ' . escapeshellarg($arg); - } - } - - $this->previousElement = $command; - $this->systemCommand .= $command; - - return isset($error) ? $error : true; - } - - // }}} - // {{{ pushOperator() - - /** - * Used to push an operator onto the running command to be executed - * - * @param string $in_operator Either string reprentation of operator or system character - * - * @access public - * @return boolean true on success {or System_Command_Error Exception} - */ - function pushOperator($in_operator) - { - if ($this->_initError) { - return $this->_initError; - } - - $operator = isset($this->controlOperators[$in_operator]) ? $this->controlOperators[$in_operator] : $in_operator; - - if (is_null($this->previousElement) || in_array($this->previousElement, $this->controlOperators)) { - $this->commandStatus = -1; - $error = PEAR::raiseError(null, SYSTEM_COMMAND_OPERATOR_PLACEMENT, null, E_USER_WARNING, null, 'System_Command_Error', true); - } - elseif (!in_array($operator, $this->controlOperators)) { - $this->commandStatus = -1; - $error = PEAR::raiseError(null, SYSTEM_COMMAND_INVALID_OPERATOR, null, E_USER_WARNING, $operator, 'System_Command_Error', true); - } - - $this->previousElement = $operator; - $this->systemCommand .= ' ' . $operator . ' '; - return isset($error) ? $error : true; - } - - // }}} - // {{{ execute() - - /** - * Executes the code according to given options - * - * @return bool true if success {or System_Command_Exception} - * - * @access public - */ - function execute() - { - if ($this->_initError) { - return $this->_initError; - } - - // if the command is empty or if the last element was a control operator, we can't continue - if (is_null($this->previousElement) || $this->commandStatus == -1 || in_array($this->previousElement, $this->controlOperators)) { - return PEAR::raiseError(null, SYSTEM_COMMAND_INVALID_COMMAND, null, E_USER_WARNING, $this->systemCommand, 'System_Command_Error', true); - } - - // Warning about impossible mix of options - if (!empty($this->options['OUTPUT'])) { - if (!empty($this->options['SHUTDOWN']) || !empty($this->options['NOHUP'])) { - return PEAR::raiseError(null, SYSTEM_COMMAND_NO_OUTPUT, null, E_USER_WARNING, null, 'System_Command_Error', true); - } - } - - // if this is not going to stdout, then redirect to /dev/null - if (empty($this->options['OUTPUT'])) { - $this->systemCommand .= ' >/dev/null'; - } - - $suffix = ''; - // run a command immune to hangups, with output to a non-tty - if (!empty($this->options['NOHUP'])) { - $this->systemCommand = $this->options['NOHUP'] . $this->systemCommand; - } - // run a background process (only if not nohup) - elseif (!empty($this->options['BACKGROUND'])) { - $suffix = ' &'; - } - - // Register to be run on shutdown - if (!empty($this->options['SHUTDOWN'])) { - $line = "system(\"{$this->systemCommand}$suffix\");"; - $function = create_function('', $line); - register_shutdown_function($function); - return true; - } - else { - // send stderr to a file so that we can reap the error message - $tmpFile = tempnam($this->tmpDir, 'System_Command-'); - $this->systemCommand .= ' 2>' . $tmpFile . $suffix; - $shellPipe = $this->which('echo') . ' ' . escapeshellarg($this->systemCommand) . ' | ' . $this->options['SHELL']; - exec($shellPipe, $result, $returnVal); - - if ($returnVal !== 0) { - // command returned nonzero; that's always an error - $return = PEAR::raiseError(null, SYSTEM_COMMAND_NONZERO_EXIT, null, E_USER_WARNING, null, 'System_Command_Error', true); - } - else if (!$this->options['STDERR']) { - // caller does not care about stderr; return success - $return = implode("\n", $result); - } - else { - // our caller cares about stderr; check stderr output - clearstatcache(); - if (filesize($tmpFile) > 0) { - // the command actually wrote to stderr - $stderr_output = file_get_contents($tmpFile); - $return = PEAR::raiseError(null, SYSTEM_COMMAND_STDERR, null, E_USER_WARNING, $stderr_output, 'System_Command_Error', true); - } else { - // total success; return stdout gathered by exec() - $return = implode("\n", $result); - } - } - - unlink($tmpFile); - return $return; - } - } - - // }}} - // {{{ which() - - /** - * Functionality similiar to unix 'which'. Searches the path - * for the specified program. - * - * @param $cmd name of the executable to search for - * - * @access private - * @return string returns the full path if found, false if not - */ - function which($in_cmd) - { - // only pass non-empty strings to System::which() - if (!is_string($in_cmd) || '' === $in_cmd) { - return(false); - } - - // explicitly pass false as fallback value - return System::which($in_cmd, false); - } - - // }}} - // {{{ reset() - - /** - * Prepare for a new command to be built - * - * @access public - * @return void - */ - function reset() - { - $this->previousElement = null; - $this->systemCommand = null; - $this->commandStatus = 0; - } - - // }}} - // {{{ errorMessage() - - /** - * Return a textual error message for a System_Command error code - * - * @param integer error code - * - * @return string error message, or false if the error code was - * not recognized - */ - function errorMessage($in_value) - { - static $errorMessages; - if (!isset($errorMessages)) { - $errorMessages = array( - SYSTEM_COMMAND_OK => 'no error', - SYSTEM_COMMAND_ERROR => 'unknown error', - SYSTEM_COMMAND_NO_SHELL => 'no shell found', - SYSTEM_COMMAND_INVALID_SHELL => 'invalid shell', - SYSTEM_COMMAND_TMPDIR_ERROR => 'could not create temporary directory', - SYSTEM_COMMAND_INVALID_OPERATOR => 'control operator invalid', - SYSTEM_COMMAND_INVALID_COMMAND => 'invalid system command', - SYSTEM_COMMAND_OPERATOR_PLACEMENT => 'invalid placement of control operator', - SYSTEM_COMMAND_COMMAND_PLACEMENT => 'invalid placement of command', - SYSTEM_COMMAND_NOHUP_MISSING => 'nohup not found on system', - SYSTEM_COMMAND_NO_OUTPUT => 'output not allowed', - SYSTEM_COMMAND_STDERR => 'command wrote to stderr', - SYSTEM_COMMAND_NONZERO_EXIT => 'non-zero exit value from command', - ); - } - - if (System_Command::isError($in_value)) { - $in_value = $in_value->getCode(); - } - - return isset($errorMessages[$in_value]) ? $errorMessages[$in_value] : $errorMessages[SYSTEM_COMMAND_ERROR]; - } - - // }}} - // {{{ isError() - - /** - * Tell whether a result code from a System_Command method is an error - * - * @param int result code - * - * @return bool whether $in_value is an error - * - * @access public - */ - function isError($in_value) - { - return (is_object($in_value) && - (strtolower(get_class($in_value)) == 'system_command_error' || - is_subclass_of($in_value, 'system_command_error'))); - } - - // }}} -} - -// {{{ class System_Command_Error - -/** - * System_Command_Error constructor. - * - * @param mixed System_Command error code, or string with error message. - * @param integer what "error mode" to operate in - * @param integer what error level to use for $mode & PEAR_ERROR_TRIGGER - * @param mixed additional debug info, such as the last query - * - * @access public - * - * @see PEAR_Error - */ - -// }}} -class System_Command_Error extends PEAR_Error -{ - // {{{ properties - - /** - * Message in front of the error message - * @var string $error_message_prefix - */ - var $error_message_prefix = 'System_Command Error: '; - - // }}} - // {{{ constructor - - function System_Command_Error($code = SYSTEM_COMMAND_ERROR, $mode = PEAR_ERROR_RETURN, - $level = E_USER_NOTICE, $debuginfo = null) - { - if (is_int($code)) { - $this->PEAR_Error(System_Command::errorMessage($code), $code, $mode, $level, $debuginfo); - } else { - $this->PEAR_Error("Invalid error code: $code", SYSTEM_COMMAND_ERROR, $mode, $level, $debuginfo); - } - } - - // }}} -} -?>