| // +----------------------------------------------------------------------+ // define('CMD_RCSID', '$Id$'); /** * The Cmd:: 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 * @version $Revision$ **/ require_once 'PEAR.php'; class Cmd extends PEAR { var $arrSetting = array(); var $arrConstant = array(); var $arrCommand = array(); /** * Class constructor * * Defines all necessary constants and sets defaults * * @author Anders Johannsen * * @access public * **/ function Cmd () { // Defining constants $this->arrConstant = array ("CMD_SEQUENCE", "CMD_SHUTDOWN", "CMD_SHELL", "CMD_OUTPUT", "CMD_NOHUP", "CMD_VERBOSE" ); foreach ($this->arrConstant as $key => $value) { if (!defined($value)) { define($value, $key); } } // Setting default values $this->arrSetting[CMD_SEQUENCE] = true; $this->arrSetting[CMD_SHUTDOWN] = false; $this->arrSetting[CMD_OUTPUT] = false; $this->arrSetting[CMD_NOHUP] = false; $this->arrSetting[CMD_VERBOSE] = false; $arrShell = array ("sh", "bash", "zsh", "tcsh", "csh", "ash", "sash", "esh", "ksh"); foreach ($arrShell as $shell) { if ($this->arrSetting[CMD_SHELL] = $this->which($shell)) { break; } } if (empty($this->arrSetting[CMD_SHELL])) { $this->raiseError("No shell found"); } } /** * Sets any option * * The options are currently: * CMD_SHUTDOWN : Execute commands via a shutdown function * CMD_SHELL : Path to shell * CMD_OUTPUT : Output stdout from process * CMD_NOHUP : Use nohup to detach process * CMD_VERBOSE : Print errors to stdout * * @param $option is a constant, which corresponds to the * option that should be changed * * @param $setting is the value of the option currently * being toggled. * * @return bool true if succes, else false * * @access public * * @author Anders Johannsen * **/ function setOption ($option, $setting) { if (empty($this->arrConstant[$option])) { $this->raiseError("No such option: $option"); return false; } switch ($option) { case CMD_OUTPUT: case CMD_SHUTDOWN: case CMD_VERBOSE: case CMD_SEQUENCE: $this->arrSetting[$option] = $setting; return true; break; case CMD_SHELL: if (is_executable($setting)) { $this->arrSetting[$option] = $setting; return true; } else { $this->raiseError("No such shell: $setting"); return false; } break; case CMD_NOHUP: if (empty($setting)) { $this->arrSetting[$option] = false; } else if ($location = $this->which("nohup")) { $this->arrSetting[$option] = true; } else { $this->raiseError("Nohup was not found on your system"); return false; } break; } } /** * Add command for execution * * @param $command accepts both arrays and regular strings * * @return bool true if succes, else false * * @access public * * @author Anders Johannsen * **/ function command($command) { if (is_array($command)) { foreach ($command as $key => $value) { $this->arrCommand[] = $value; } return true; } else if (is_string($command)) { $this->arrCommand[] = $command; return true; } $this->raiseError("Argument not valid"); return false; } /** * Executes the code according to given options * * @return bool true if succes, else false * * @access public * * @author Anders Johannsen * **/ function exec() { // Warning about impossible mix of options if (!empty($this->arrSetting[CMD_OUTPUT])) { if (!empty($this->arrSetting[CMD_SHUTDOWN]) || !empty($this->arrSetting[CMD_NOHUP])) { $this->raiseError("Error: Commands executed via shutdown functions or nohup cannot return output"); return false; } } // Building command $strCommand = implode(";", $this->arrCommand); $strExec = "echo '$strCommand' | ".$this->arrSetting[CMD_SHELL]; if (empty($this->arrSetting[CMD_OUTPUT])) { $strExec = $strExec . ' > /dev/null'; } if (!empty($this->arrSetting[CMD_NOHUP])) { $strExec = 'nohup ' . $strExec; } // Executing if (!empty($this->arrSetting[CMD_SHUTDOWN])) { $line = "system(\"$strExec\");"; $function = create_function('', $line); register_shutdown_function($function); return true; } else { return `$strExec`; } } /** * Errorhandler. If option CMD_VERBOSE is true, * the error is printed to stdout, otherwise it * is avaliable in lastError * * @return bool always returns true * * @access private * * @author Anders Johannsen **/ function raiseError($strError) { if (!empty($this->arrSetting[CMD_VERBOSE])) { echo $strError; } else { $this->lastError = $strError; } return true; } /** * Functionality similiar to unix 'which'. Searches the path * for the specified program. * * @param $cmd name of the executable to search for * * @return string returns the full path if found, * false if not * * @access private * * @author Anders Johannsen **/ function which($cmd) { global $HTTP_ENV_VARS; $arrPath = explode(":", $HTTP_ENV_VARS['PATH']); foreach ($arrPath as $path) { $location = $path . "/" . $cmd; if (is_executable($location)) { return $location; } } return false; } } ?>