home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / System / Daemon / OS.php < prev   
Encoding:
PHP Script  |  2008-07-02  |  14.0 KB  |  476 lines

  1. <?php
  2. /* vim: set noai expandtab tabstop=4 softtabstop=4 shiftwidth=4: */
  3. /**
  4.  * System_Daemon turns PHP-CLI scripts into daemons.
  5.  * 
  6.  * PHP version 5
  7.  *
  8.  * @category  System
  9.  * @package   System_Daemon
  10.  * @author    Kevin van Zonneveld <kevin@vanzonneveld.net>
  11.  * @copyright 2008 Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  12.  * @license   http://www.opensource.org/licenses/bsd-license.php New BSD Licence
  13.  * @version   SVN: Release: $Id$
  14.  * @link      http://trac.plutonia.nl/projects/system_daemon
  15.  */
  16.  
  17. /**
  18.  * Operating System focussed functionality.
  19.  *
  20.  * @category  System
  21.  * @package   System_Daemon
  22.  * @author    Kevin van Zonneveld <kevin@vanzonneveld.net>
  23.  * @copyright 2008 Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  24.  * @license   http://www.opensource.org/licenses/bsd-license.php New BSD Licence
  25.  * @version   SVN: Release: $Id$
  26.  * @link      http://trac.plutonia.nl/projects/system_daemon
  27.  * 
  28.  */
  29. class System_Daemon_OS
  30. {
  31.     /**
  32.      * Holds errors
  33.      *
  34.      * @var array
  35.      */
  36.     public $errors = array();
  37.     
  38.     
  39.         
  40.     /**
  41.      * Template path
  42.      *
  43.      * @var string
  44.      */
  45.     protected $autoRunTemplatePath = "";    
  46.         
  47.     /**
  48.      * Replace the following keys with values to convert a template into
  49.      * a read autorun script
  50.      *
  51.      * @var array
  52.      */
  53.     protected $autoRunTemplateReplace = array();
  54.     
  55.     
  56.     
  57.     /**
  58.      * Hold OS information
  59.      *
  60.      * @var array
  61.      */
  62.     private $_osDetails = array();
  63.     
  64.     
  65.     
  66.     /**
  67.      * Constructor
  68.      * Only run by instantiated OS Drivers
  69.      */
  70.     public function __construct() 
  71.     {
  72.         // Up to date filesystem information
  73.         clearstatcache();
  74.  
  75.         // Get ancestors
  76.         $ancs = System_Daemon_OS::_getAncestors($this);
  77.         foreach ($ancs as $i=>$anc) {
  78.             $ancs[$i] = System_Daemon_OS::_getShortHand($anc);
  79.         }        
  80.         
  81.         // Set OS Details
  82.         $this->_osDetails["shorthand"] = $this->_getShortHand(get_class($this));
  83.         $this->_osDetails["ancestors"] = $ancs;
  84.     }
  85.  
  86.     /**
  87.      * Loads all the drivers and returns the one for the most specifc OS
  88.      * 
  89.      * @param mixed   $force_os boolean or string when you want to enforce an OS 
  90.      * for testing purposes. CAN BE VERY DANGEROUS IF WRONG OS IS SPECIFIED! 
  91.      * Will otherwise autodetect OS.
  92.      * @param boolean $retried  used internally to find out wether we are retrying 
  93.      *
  94.      * @return object
  95.      */
  96.     public function &factory($force_os = false, $retried = false)
  97.     {
  98.         $drivers      = array();
  99.         $driversValid = array();
  100.         $class_prefix = "System_Daemon_OS_";
  101.         
  102.         // Load all drivers
  103.         $driver_dir = realpath(dirname(__FILE__)."/OS");
  104.         foreach (glob($driver_dir."/*.php") as $driver_path) {
  105.             // Set names
  106.             $driver = basename($driver_path, ".php");
  107.             $class  = $class_prefix.$driver;
  108.             
  109.             // Only do this for real drivers
  110.             if ($driver == "Exception" || !is_file($driver_path)) {
  111.                 continue;
  112.             }
  113.             
  114.             // Let SPL include & load the driver or Report errors
  115.             if (!class_exists($class, true)) {
  116.                 $this->errors[] = "Class ".$class." does not exist";
  117.                 return false;
  118.             }
  119.  
  120.             // Save in drivers array
  121.             $drivers[$class] = new $class;            
  122.         }
  123.         
  124.         if ($force_os !== false) {
  125.             // Let's use the Forced OS. This could be dangerous
  126.             $use_name = $class_prefix.$force_os;
  127.         } else {
  128.             // What OSes are valid for this system?
  129.             // e.g. Debian makes Linux valid as well
  130.             foreach ($drivers as $class=>$obj) {
  131.                 // Save in Installed container
  132.                 if (call_user_func(array($obj, "isInstalled"))) {
  133.                     $driversValid[$class] = $obj;         
  134.                 }
  135.             }
  136.             
  137.             // What's the most specific OS?
  138.             // e.g. Ubuntu > Debian > Linux    
  139.             $use_name = System_Daemon_OS::_mostSpecific($driversValid);
  140.         }
  141.         
  142.         // If forced driver wasn't found, retry to autodetect it
  143.         if (!isset($drivers[$use_name])) {
  144.             // Make sure we don't build a loop
  145.             if (!$retried) {
  146.                 $obj = System_Daemon_OS::factory(false, true);
  147.                 $obj->errors[] = "Unable to use driver: ".$force_os." falling ".
  148.                     "back to autodetection.";
  149.             } else {
  150.                 $obj = false;
  151.             }
  152.         } else {
  153.             $obj = $drivers[$use_name]; 
  154.         }
  155.        
  156.         return $obj;
  157.     }//end &factory()
  158.  
  159.     
  160.     
  161.     /**
  162.      * Determines wether the system is compatible with this OS
  163.      *
  164.      * @return boolean
  165.      */    
  166.     public function isInstalled() 
  167.     {
  168.         $this->errors[] = "Not implemented for OS";
  169.         return false;
  170.     }//end isInstalled
  171.     
  172.     /**
  173.      * Returns array with all the specific details of the loaded OS
  174.      *
  175.      * @return array
  176.      */
  177.     public function getDetails()
  178.     {
  179.         return $this->_osDetails;
  180.     }//end getDetails
  181.  
  182.     /**
  183.      * Returns a template path to base the autuRun script on.
  184.      * Uses $autoRunTemplatePath if possible. 
  185.      *
  186.      * @return unknown
  187.      * @see autoRunTemplatePath
  188.      */
  189.     public function getAutoRunTemplatePath() 
  190.     {
  191.         if (!$this->autoRunTemplatePath) {
  192.             $this->errors[] = "No autoRunTemplatePath found";
  193.             return false;
  194.         }
  195.         
  196.         return $this->autoRunTemplatePath; 
  197.     }//end getAutoRunTemplatePath        
  198.     
  199.     /**
  200.      * Returns OS specific path to autoRun file
  201.      * 
  202.      * @param string $appName Unix-proof name of daemon
  203.      *
  204.      * @return string
  205.      */
  206.     public function getAutoRunPath($appName) 
  207.     {
  208.         if (!$this->autoRunDir) {
  209.             $this->errors[] = "autoRunDir is not set";
  210.             return false;
  211.         }
  212.         
  213.         $path = $this->autoRunDir."/".$appName;
  214.         
  215.         // Path exists
  216.         if (!is_dir($dir = dirname($path))) {
  217.             $this->errors[] = "Directory: '".$dir."' does not exist. ".
  218.                 "How can this be a correct path?";
  219.             return false;
  220.         }
  221.         
  222.         // Is writable?
  223.         if (!is_writable($dir)) {
  224.             $this->errors[] = "Directory: '".$dir."' is not writable. ".
  225.                 "Maybe run as root?";
  226.             return false;
  227.         }
  228.         
  229.         return $path;
  230.     }//end getAutoRunPath    
  231.     
  232.     /**
  233.      * Returns a template to base the autuRun script on.
  234.      * Uses $autoRunTemplatePath if possible. 
  235.      *
  236.      * @return unknown
  237.      * @see autoRunTemplatePath
  238.      */
  239.     public function getAutoRunTemplate() 
  240.     {
  241.         if (($path = $this->getAutoRunTemplatePath()) === false) {
  242.             return false;
  243.         }
  244.         
  245.         if (!file_exists($path)) {
  246.             $this->errors[] = "autoRunTemplatePath: ".
  247.                 $path." does not exist";
  248.             return false;
  249.         }
  250.         
  251.         return file_get_contents($this->autoRunTemplatePath);
  252.     }//end getAutoRunTemplate    
  253.          
  254.     /**
  255.      * Uses properties to enrich the autuRun Template
  256.      *
  257.      * @param array $properties Contains the daemon properties
  258.      * 
  259.      * @return mixed string or boolean on failure
  260.      */
  261.     public function getAutoRunScript($properties)    
  262.     {
  263.         
  264.         // All data in place? 
  265.         if (($template = $this->getAutoRunTemplate()) === false) {
  266.             return false;
  267.         }
  268.         if (!$this->autoRunTemplateReplace 
  269.             || !is_array($this->autoRunTemplateReplace)
  270.             || !count($this->autoRunTemplateReplace)) {
  271.             return false;
  272.         }
  273.         
  274.         // Replace System specific keywords with Universal placeholder keywords
  275.         $script = str_replace(array_keys($this->autoRunTemplateReplace), 
  276.             array_values($this->autoRunTemplateReplace), 
  277.             $template);
  278.         
  279.         // Replace Universal placeholder keywords with Daemon specific properties
  280.         if (!preg_match_all('/(\{PROPERTIES([^\}]+)\})/is', $script, $r)) {
  281.             $this->errors[] = "No PROPERTIES found in autoRun template";
  282.             return false;
  283.         }
  284.         
  285.         $placeholders = $r[1];
  286.         array_unique($placeholders);
  287.         foreach ($placeholders as $placeholder) {
  288.             // Get var
  289.             $var = str_replace(array("{PROPERTIES.", "}"), "", $placeholder);
  290.             
  291.             // Replace placeholder with actual daemon property
  292.             $script = str_replace($placeholder, $properties[$var], $script);
  293.         }
  294.         
  295.         return $script;        
  296.     }//end getAutoRunScript()   
  297.     
  298.     /**
  299.      * Writes an: 'init.d' script on the filesystem
  300.      * combining
  301.      * 
  302.      * @param array   $properties Contains the daemon properties
  303.      * @param boolean $overwrite  Wether to overwrite when the file exists 
  304.      * 
  305.      * @return mixed string or boolean on failure
  306.      * @see getAutoRunScript()
  307.      * @see getAutoRunPath()
  308.      */
  309.     public function writeAutoRun($properties, $overwrite = false)
  310.     {
  311.         // Check properties
  312.         if ($this->_testAutoRunProperties($properties) === false) {
  313.             // Explaining errors should have been generated by 
  314.             // previous function already
  315.             return false;
  316.         }
  317.         
  318.         // Get script body
  319.         if (($body = $this->getAutoRunScript($properties)) === false) {
  320.             // Explaining errors should have been generated by 
  321.             // previous function already
  322.             return false;
  323.         }
  324.         
  325.         // Get script path
  326.         if (($path = $this->getAutoRunPath($properties["appName"])) === false) {
  327.             // Explaining errors should have been generated by 
  328.             // previous function already            
  329.             return false;
  330.         }
  331.         
  332.         // Overwrite?
  333.         if (file_exists($path) && !$overwrite) {
  334.             return true;
  335.         }
  336.         
  337.         // Write
  338.         if (!file_put_contents($path, $body)) {
  339.             $this->errors[] =  "startup file: '".
  340.                 $path."' cannot be ".
  341.                 "written to. Check the permissions";
  342.             return false;
  343.         }
  344.  
  345.         // Chmod
  346.         if (!chmod($path, 0777)) {
  347.             $this->errors[] =  "startup file: '".
  348.                 $path."' cannot be ".
  349.                 "chmodded. Check the permissions";
  350.             return false;
  351.         } 
  352.         
  353.         
  354.         return $path;
  355.     }//end writeAutoRun() 
  356.             
  357.     
  358.         
  359.     /**
  360.      * Sets daemon specific properties
  361.      *  
  362.      * @param array $properties Contains the daemon properties
  363.      * 
  364.      * @return array
  365.      */       
  366.     private function _testAutoRunProperties($properties = false) 
  367.     {
  368.         $required_props = array("appName", "appExecutable", 
  369.             "appDescription", "appDir", "authorName", "authorEmail");
  370.         
  371.         // Valid array?
  372.         if (!is_array($properties) || !count($properties)) {
  373.             $this->errors[] = "No properties to ".
  374.                 "forge init.d script";
  375.             return false; 
  376.         }
  377.                 
  378.         // Check if all required properties are available
  379.         $success = true;
  380.         foreach ($required_props as $required_prop) {
  381.             if (!isset($properties[$required_prop])) {
  382.                 $this->errors[] = "Cannot forge an ".
  383.                     "init.d script without a valid ".
  384.                     "daemon property: ".$required_prop;
  385.                 $success        = false;
  386.                 continue;
  387.             }            
  388.         }
  389.         
  390.         // Path to daemon
  391.         $daemon_filepath = $properties["appDir"]."/".$properties["appExecutable"];
  392.         
  393.         // Path to daemon exists?
  394.         if (!file_exists($daemon_filepath)) {
  395.             $this->errors[] = "unable to forge startup script for non existing ".
  396.                 "daemon_filepath: ".$daemon_filepath.", try setting a valid ".
  397.                 "appDir or appExecutable";
  398.             $success        = false;
  399.         }
  400.         
  401.         // Path to daemon is executable? 
  402.         if (!is_executable($daemon_filepath)) {
  403.             $this->errors[] = "unable to forge startup script. ".
  404.                 "daemon_filepath: ".$daemon_filepath.", needs to be executable ".
  405.                 "first";
  406.             $success        = false;
  407.         }
  408.         
  409.         return $success;
  410.         
  411.     } //end _testAutoRunProperties    
  412.         
  413.     /**
  414.      * Determines how specific an operating system is.
  415.      * e.g. Ubuntu is more specific than Debian is more 
  416.      * specific than Linux is more specfic than Common.
  417.      * Determined based on class hierarchy.
  418.      *
  419.      * @param array $classes Array with keys with classnames
  420.      * 
  421.      * @return string
  422.      */
  423.     private function _mostSpecific($classes) 
  424.     {
  425.         $weights = array_map(array("System_Daemon_OS", "_getAncestorCount"), 
  426.             $classes);
  427.         arsort($weights);        
  428.         return reset(array_keys($weights));
  429.     }//end _mostSpecific
  430.     
  431.     /**
  432.      * Extracts last part of a classname. e.g. System_Daemon_OS_Ubuntu -> Ubuntu
  433.      *
  434.      * @param string $class Full classname
  435.      * 
  436.      * @return string
  437.      */
  438.     private function _getShortHand($class) 
  439.     {
  440.         if (!is_string($class) || ! $class ) {
  441.             return false;
  442.         }
  443.         $parts = explode("_", $class);
  444.         return end($parts);
  445.     } //end _getShortHand
  446.     
  447.     /**
  448.      * Get the total parent count of a class
  449.      *
  450.      * @param string $class Full classname or instance
  451.      * 
  452.      * @return integer
  453.      */
  454.     private function _getAncestorCount($class) 
  455.     {
  456.         return count(System_Daemon_OS::_getAncestors($class));        
  457.     }//end _getAncestorCount
  458.     
  459.     /**
  460.      * Get an array of parent classes
  461.      *
  462.      * @param string $class Full classname or instance
  463.      * 
  464.      * @return array
  465.      */
  466.     private function _getAncestors($class)
  467.     {
  468.         $classes = array();
  469.         while ($class = get_parent_class($class)) { 
  470.             $classes[] = $class; 
  471.         }
  472.         return $classes;
  473.     }//end _getAncestors
  474.     
  475. }//end class
  476. ?>