--- /dev/null
+<?php
+//
+// +----------------------------------------------------------------------+
+// | PHP version 4.0 |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2001 The PHP Group |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.02 of the PHP license, |
+// | that is bundled with this package in the file LICENSE, and is |
+// | available at through the world-wide-web at |
+// | http://www.php.net/license/2_02.txt. |
+// | If you did not receive a copy of the PHP license and are unable to |
+// | obtain it through the world-wide-web, please send a note to |
+// | license@php.net so we can mail you a copy immediately. |
+// +----------------------------------------------------------------------+
+// | Authors: Anders Johannsen <anders@johannsen.com> |
+// | |
+// +----------------------------------------------------------------------+
+//
+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 <anders@johannsen.com>
+ * @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 <anders@johannsen.com>
+ *
+ * @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 <anders@johannsen.com>
+ *
+ **/
+
+ 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 <anders@johannsen.com>
+ *
+ **/
+
+ 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 <anders@johannsen.com>
+ *
+ **/
+
+ 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 <anders@johannsen.com>
+ **/
+
+ 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 <anders@johannsen.com>
+ **/
+
+ 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;
+ }
+}
+
+?>